home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Compilers⁄Interps / kevoSource / prim.c < prev    next >
Text File  |  1993-05-18  |  75KB  |  2,981 lines

  1. /* Kevo -- a prototype-based object-oriented language */
  2. /* (c) Antero Taivalsaari 1991-1993                   */
  3. /* Some parts (c) Antero Taivalsaari 1986-1988           */
  4. /* prim.c: Portable system primitives                  */
  5.  
  6. #include "global.h"
  7. #include "portGlobal.h"
  8.  
  9. /*---------------------------------------------------------------------------*/
  10. /* Special user-level execution primitives */ 
  11.  
  12. /*
  13.    Most of the definitions in this file are visible to the user via 
  14.    the 'SystemRoot' context, although many of the primitives should not 
  15.    be invoked directly. The definitions whose names have been put within 
  16.    parentheses (xxx) or square brackets <xxx> are those that should be invoked 
  17.    only if you relly know what you are doing. Direct invocation of these primitives
  18.    will probably crash the system.
  19. */
  20.  
  21. /* execute    ( object --  ) */
  22. /* execute an object given its identity */
  23. void pExecute()
  24. {
  25.   execute((OBJECT*)popData());
  26. }
  27.     
  28.  
  29. /* <executeStore>    ( store --  ) */
  30. /* execute code given the memory address where the code begins */
  31. /* This operation should not normally be called directly, because */
  32. /* resizing etc. may physically move the location of code */
  33. void pExecStore()
  34. {
  35.   pushReturn((int*)ip);
  36.   ip = (int**)popData();
  37. }
  38.     
  39.  
  40. /* exit        (  --  ) */
  41. /* end the execution of a thread and return to the next level */
  42. void pExit()
  43. {
  44.   ip = (int**)popReturn();
  45. }
  46.  
  47.  
  48. /* freeExit        ( storeAddress --  ) */
  49. /* end the execution of a thread and return to the next level */
  50. /* deallocate the store space of the code, too */
  51. /* This operation is used to finalize the execution of */
  52. /* interactively typed code */
  53. void pFreeExit()
  54. {
  55.   free((void*)popData());
  56.   ip = (int**)popReturn();
  57. }
  58.  
  59.  
  60. /*---------------------------------------------------------------------------*/
  61. /* Data access primitives */ 
  62.  
  63. /* (=sharedVar)    ( -- addr ) */
  64. /* return the address of a task-independent (shared) variable */
  65. void pSharedVar()
  66. {
  67.   pushData((int)ip);
  68.   ip = (int**)popReturn();
  69. }
  70.  
  71.  
  72. /* (=taskVar)    ( -- addr ) */
  73. /* return the address of a task-specific variable */
  74. /* '*up' is a shorthand for getting the address of up's store part (->mfa)' */
  75. void pTaskVar()
  76. {
  77.   pushData((int)((int*)*up + (int)*ip));    
  78.   ip = (int**)popReturn();
  79. }
  80.  
  81.  
  82. /* (=sharedConst)    ( -- value ) */
  83. /* return the value of a task-independent (shared) constant */
  84. void pSharedConst()
  85. {
  86.   pushData((int)*ip);
  87.   ip = (int**)popReturn();
  88. }
  89.  
  90.   
  91. /* (=taskConst)        ( -- value ) */
  92. /* return the value of a task-specific constant */
  93. void pTaskConst()
  94. {
  95.   pushData(*((int*)*up + (int)*ip));
  96.   ip = (int**)popReturn();
  97. }
  98.  
  99.  
  100. /* (=context)    ( -- object ) */
  101. /* return the identity (self) of a context object (object-oriented object) */
  102. void pContext()
  103. {
  104.     /* 'op' is a pointer to latest object (handle). */
  105.     /* It is updated by the inner interpreter */
  106.     ip = (int**)popReturn();
  107.     pushData((int)op);
  108.  
  109. /*
  110.     Old implementation:
  111.     Comment: This implementation does not yield the same result 
  112.     when executed directly and via "' xxx execute". I haven't noticed 
  113.     this to cause any trouble, but 'op' is safer.
  114.  
  115.     ip = (int**)popReturn();
  116.     pushData((int)*(ip-1));
  117. */
  118. }
  119.   
  120.  
  121. /* (=REF)        (  -- value ) <or> ( value --  ) */
  122. /* return/assign value from/to a shared to-variable */
  123. void pREF()
  124. {
  125.     if ((*up)->assigning) {
  126.         /* Store the value to the slot */
  127.         *ip = (int*)popData();
  128.         (*up)->assigning--;
  129.     }
  130.     else {
  131.         /* Fetch the value from the slot */
  132.         pushData((int)*ip);
  133.     }
  134.      ip = (int**)popReturn();
  135. }
  136.  
  137.  
  138. /* (=VAR)         (  -- value ) <or> ( value --  ) */
  139. /* return/assign value from/to an OOP object-specific to-variable */
  140. void pVAR()
  141. {
  142.   int* address = (int*)*topContext + (int)*ip;
  143.   
  144.     if ((*up)->assigning) {
  145.           /* Store the value to the slot */
  146.         *address = popData();
  147.         (*up)->assigning--;
  148.     }
  149.     else {
  150.         /* Fetch the value from the slot */
  151.         pushData(*address);
  152.     }
  153.      ip = (int**)popReturn();
  154. }
  155.  
  156.  
  157. /* (->)        (  --  ) */
  158. /* Increment the value of the 'assigning' variable so as to */
  159. /* enforce assigment next time (=REF) or (=VAR) is executed */
  160. void pIncAss()
  161. {
  162.     (*up)->assigning++;
  163. }
  164.  
  165.  
  166. /* (lit)     ( -- l ) */
  167. /* load a literal to the data stack */
  168. void pLit()
  169. {
  170.   pushData((int)*ip++);
  171. }
  172.  
  173.  
  174. /* ("lit)     ( -- straddr ) */
  175. /* load a string literal (address) to the data stack */
  176. /* Remember: string literals should not contain double carats (^^) or */
  177. /* carriage returns: image files containing such characters will not read */
  178. void pStrLit()
  179. {
  180.   pushData((int)*ip++);
  181. }
  182.  
  183.  
  184. /* (=sharedVector)    (  --  ) */
  185. void pSharedVector()
  186. /* task-independent (shared) vector execution (vector is a memory  */
  187. /* location which contains a pointer to an executable code object) */
  188. {
  189.   OBJECT* object = (OBJECT*)*ip;
  190.   ip = (int**)popReturn();;
  191.   execute(object);
  192. }
  193.   
  194.  
  195. /* (=taskVector)    (  --  ) */
  196. /* task-specific vectored execution */ 
  197. /* '*up' is a shorthand for getting the address of up's store part (->mfa)' */
  198. void pTaskVector()
  199. {
  200.   OBJECT* object = (OBJECT*)(*((int*)*up + (int)*ip));
  201.   ip = (int**)popReturn();
  202.   execute(object);
  203. }
  204.  
  205.  
  206. /*---------------------------------------------------------------------------*/
  207. /* Temporary variable (block) operations */ 
  208.  
  209. /* These operations allow the definition of temporary variables (blocks). */
  210. /* They allow you to considerably reduce the need for stack juggling operations */
  211.  
  212. /* Note that in the current implementation blocks should not be nested */
  213. /* because the references to temporaries have access to the latest frame */
  214. /* only; thus, references from within blocks to temporaries defined in outer */
  215. /* blocks will be incorrect. Otherwise, blocks work just fine (even with DO-LOOPs). */
  216.  
  217. /* Also keep in mind that the return stack is by default quite small */
  218. /* and it DOESN'T grow automatically. Thus, if you use a lot of temps, */
  219. /* you'd better allocate enough space using 'resizeReturnStack'. */
  220.  
  221. /* ({)        (  --  ) */
  222. /* Open a frame for temporary variables (runtime operation) */
  223. void pOpenFrame()
  224. {
  225.     pushReturn((int*)(*up)->fp); /* Store the previous frame pointer to RStack */
  226.     (*up)->fp = returnSp;         /* Set the frame pointer */
  227. }
  228.  
  229.  
  230. /* (})        (  --  ) */
  231. /* Close the current frame (runtime operation) */
  232. void pCloseFrame()
  233. {
  234.     returnSp = (*up)->fp;
  235.     (*up)->fp = (int**)popReturn();
  236. }
  237.  
  238.  
  239. /* <temp>    ( data --  ) <or> (  --  ) */
  240. /* Allocate a temporary variable within the current frame (runtime operation) */
  241. /* This is a to-operation, which either initializes the temporary variable */
  242. /* with the desired value, or alternatively initializes it to zero */
  243. void pAllocTemp()
  244. {
  245.     if ((*up)->assigning) {
  246.         pushReturn((int*)popData());
  247.         (*up)->assigning--;
  248.     }
  249.     else pushReturn(0);
  250.  
  251.  
  252. /* temp:    ( data --  ) <or> (  -- data ) */
  253. /* Access the value of a temporary variable (runtime operation) */
  254. /* using the index which is given as a literal parameter (follows this */
  255. /* operation in the thread). This too is a to-variable, which either */
  256. /* stores or fetches the value depending on the assignment counter. */
  257. void pAccessTemp()
  258. {
  259.   int* address = (int*)(*up)->fp + (int)*ip;
  260.   
  261.     if ((*up)->assigning) {
  262.           /* Store the value to the slot in the frame */
  263.         *address = popData();
  264.         (*up)->assigning--;
  265.     }
  266.     else {
  267.         /* Fetch the value from the slot in the frame */
  268.         pushData(*address);
  269.     }
  270.  
  271.     /* Skip the offset value */
  272.      ip++;
  273. }    
  274.     
  275.  
  276. /*---------------------------------------------------------------------------*/
  277. /* Data stack operations */ 
  278.  
  279. /* Kevo implements most of Forth's traditional data stack operations */
  280. /* Owing to the presence of temporary variables (blocks), most of these */
  281. /* operations are not however needed too often */
  282.  
  283. /* drop        ( l -- ) */
  284. /* drop the topmost item in the data stack */
  285. void pDrop()
  286. {
  287.   nPopData(1);
  288. }
  289.  
  290.  
  291. /* 2drop    ( l1 l2 -- ) */
  292. /* drop two topmost items in the data stack */
  293. void pDrop2()
  294. {
  295.   nPopData(2);    /* This is a macro (see 'global.h') */
  296. }
  297.  
  298.  
  299. /* over     ( l1 l2 -- l1 l2 l1 ) */
  300. /* copy the second item in the stack to the top */
  301. void pOver()
  302. {
  303.   pushData(secondData);
  304. }
  305.  
  306.  
  307. /* 2over     ( l1 l2 l3 l4 -- l1 l2 l3 l4 l1 l2 ) */
  308. /* the same as 'over' but do two items at a time */
  309. void pOver2()
  310. {
  311.   int a = thirdData;
  312.   int b = fourthData;
  313.   pushData(b);
  314.   pushData(a);
  315. }
  316.  
  317.  
  318. /* dup        ( l -- l l ) */
  319. /* duplicate the topmost stack item */
  320. void pDup()
  321. {
  322.   pushData(topData);
  323. }
  324.  
  325.  
  326. /* 2dup     ( l1 l2  -- l1 l2 l1 l2 ) */
  327. /* duplicate two topmost stack items */
  328. void pDup2()
  329. {
  330.   int a = topData;
  331.   int b = secondData;
  332.   pushData(b);
  333.   pushData(a);
  334. }
  335.  
  336.  
  337. /* ?dup         ( l -- l l ) tai ( 0 -- 0 ) */
  338. /* duplicate the topmost stack item if it is nonzero */
  339. void pQDup()
  340. {
  341.   if (topData) pushData(topData);
  342. }
  343.  
  344.  
  345. /* nip        ( l1 l2 -- l2 ) */
  346. /* drop the second item in the data stack */
  347. void pNip()
  348. {
  349.   int temp = popData();
  350.   topData = temp;
  351. }
  352.  
  353.  
  354. /* tuck     ( l1 l2 -- l2 l1 l2 ) */
  355. /* copy the topmost stack item and tuck in under the second one */
  356. void pTuck()
  357. {
  358.   int a = topData;
  359.   int b = secondData;
  360.   secondData = a;
  361.   topData = b;
  362.   pushData(a);
  363. }
  364.  
  365.  
  366. /* swap        ( l1 l2 -- l2 l1 ) */
  367. /* change the two topmost stack items with each other */
  368. void pSwap()
  369. {
  370.   int a = topData;
  371.   int b = secondData;
  372.   topData = b;
  373.   secondData = a;
  374. }
  375.  
  376.  
  377. /* 2swap     ( l1 l2 l3 l4 -- l3 l4 l1 l2 ) */
  378. /* same as 'swap' but do two items at a time */
  379. void pSwap2()
  380. {
  381.   int a = topData;
  382.   int b = secondData;
  383.   int c = thirdData;
  384.   int d = fourthData;
  385.   fourthData = b;
  386.   thirdData = a;
  387.   secondData = d;
  388.   topData = c;
  389. }
  390.  
  391.  
  392. /* rot        ( l1 l2 l3 -- l2 l3 l1 ) */
  393. /* rotate the third topmost item in the stack to the top */
  394. void pRot()
  395. {
  396.   int a = topData;
  397.   int b = secondData;
  398.   int c = thirdData;
  399.   thirdData = b;
  400.   secondData = a;
  401.   topData = c;
  402. }
  403.  
  404.  
  405. /* -rot        ( l1 l2 l3 -- l3 l1 l2 ) */
  406. /* rotate the topmost item in the stack to the third position */
  407. void pRor()
  408. {
  409.   int a = topData;
  410.   int b = secondData;
  411.   int c = thirdData;
  412.   thirdData = a;
  413.   secondData = c;
  414.   topData = b;
  415. }
  416.  
  417.  
  418. /* pick       ( l -- l ) */
  419. /* pick the nth item in the data stack and copy it to the top */
  420. /* top of the stack = 1, next = 2, etc. */
  421. /* Note that indexing is different than in ANSI Forth */
  422. void pPick()
  423. {
  424.   int temp;
  425.   int n = topData;
  426.   nPopData(n);        /* Macro: see 'global.h' */
  427.   temp = topData; 
  428.   nPushData(n);        /*         - " -              */
  429.   topData = temp;
  430. }
  431.  
  432.  
  433. /* roll        ( n --  ) */
  434. /* 
  435.     If n > 0, bring the n'th item in the data stack to the top
  436.     by rolling the first n items 
  437.     e.g., 1 2 3 4 5 -> 5 roll -> 2 3 4 5 1
  438.     
  439.     If n < 0, move the top item in the stack to the -n'th place
  440.     e.g., 1 2 3 4 5 -> -5 roll -> 5 1 2 3 4
  441. */
  442. void pRoll()
  443. {
  444.   int* tempSp;
  445.   int  temp;
  446.   int  n = popData();
  447.  
  448.     if (n == 0) return;
  449.  
  450.     if (n > 0) {
  451.         tempSp = dataSp - n + 1;
  452.         temp = *tempSp++;
  453.  
  454.         while (tempSp <= dataSp) {
  455.             n = *tempSp--;
  456.             *tempSp = n; tempSp += 2;
  457.         }
  458.         topData = temp;
  459.     }
  460.     else {
  461.         tempSp = dataSp + n + 1;
  462.         temp = *dataSp;
  463.         
  464.         while (tempSp <= dataSp) {
  465.             n = *tempSp;
  466.             *tempSp = temp;
  467.             tempSp++; temp = n;
  468.         }
  469.     }
  470. }
  471.  
  472.  
  473. /* depth    (  -- l ) */
  474. /* push the depth of data stack to the top of data stack */
  475. /* (depth itself is not included in the count) */
  476. void pDepth()
  477. {
  478.   pushData(dataSp - dataStackBottom());
  479. }
  480.  
  481.  
  482. /* .s        (  --  ) */
  483. /* Print the contents of data stack to outfile, */
  484. /* trying to decompile possible names and types. */
  485. void pPrintStack()
  486. {
  487.   int* ptr = dataStackBottom();
  488.   if (dataSp <= dataStackBottom()) return; 
  489.  
  490.   while (dataSp >= ++ptr) {
  491.       PAIR* pair = findNameForward(*ptr);
  492.  
  493.       if (pair) ownPrintf("%s ", pair->nfa);
  494.     else {
  495.         pair = findTypeForward(*ptr);
  496.         if (pair) {
  497.             ownPrintf("%s:", pair->nfa);
  498.             ownPrintf("%d ", *ptr);
  499.         }
  500.         else ownPrintf("%d ", *ptr);
  501.     }
  502.   }
  503. }
  504.     
  505.  
  506. /* resizeDataStack    ( newSize task --  ) */
  507. /* resize the data stack of the given task */
  508. void pResizeData()
  509. {
  510.   TASK** thisTask = (TASK**)popData();
  511.   int    newSize  = popData();
  512.  
  513.     resizeDataStack(thisTask, newSize);
  514. }
  515.  
  516.  
  517. /*---------------------------------------------------------------------------*/
  518. /* Return stack operations */ 
  519.  
  520. /*
  521.    These should not be used (except for i, j, rdepth and .rs),
  522.    unless you really know what you are doing.
  523. */
  524.  
  525. /* >r        ( l -- ) */
  526. /* push a value to the return stack */
  527. void pToR()
  528. {
  529.   pushReturn((int*)popData());
  530. }
  531.  
  532.  
  533. /* r@        ( -- l ) */
  534. /* fetch the value of the topmost item in the return stack */
  535. void pRFetch()
  536. {
  537.   pushData((int)topReturn);
  538. }
  539.  
  540.  
  541. /* r>         ( -- l ) */
  542. /* pop the topmost item in the return stack to the data stack */
  543. void pRFrom()
  544. {
  545.   pushData((int)popReturn());
  546. }
  547.  
  548.  
  549. /* i        ( -- l ) */
  550. /* fetch the value of the topmost item in the return stack */
  551. void pI()
  552. {
  553.   pushData((int)topReturn);
  554. }
  555.  
  556.  
  557. /* j         ( -- l ) */
  558. /* push the index of the second nested loop to the data stack */
  559. void pJ()
  560. {
  561.   pushData((int)fourthReturn);
  562. }
  563.  
  564.  
  565. /* rdepth    (  -- l ) */
  566. /* push the depth of the return stack to the data stack */
  567. void pRDepth()
  568. {
  569.   pushData(returnSp - returnStackBottom());
  570. }
  571.  
  572.  
  573. /* dup>r        ( l -- l ) */
  574. /* push a value to the return stack without deleting it from data stack */
  575. void pDupToR()
  576. {
  577.   pushReturn((int*)topData);
  578. }
  579.  
  580.  
  581. /* r>drop        (  --  ) */
  582. /* drop a value from the return stack */
  583. void pRFromDrop()
  584. {
  585.   nPopReturn(1);
  586. }
  587.  
  588.  
  589. /* .rs        (  --  ) */
  590. /* print the contents of the return stack to outfile */
  591. /* in decompiled form. Segmentation violations may cause */
  592. /* some problems (in Unix) */
  593. void pPrintRStack()
  594. {
  595.   int** ptr = returnStackBottom();
  596.  
  597.     if (returnSp <= returnStackBottom()) return; 
  598.  
  599.     while (returnSp >= ++ptr) {
  600.         PAIR* pair = findNameForward(maskedFetch(*ptr));
  601.  
  602.         if (pair) ownPrintf("%s ", pair->nfa);
  603.         else ownPrintf("%d ", *ptr);
  604.   }
  605. }
  606.  
  607.  
  608. /* resizeReturnStack    ( newSize task --  ) */
  609. /* resize the return stack of the given task */
  610. void pResizeReturn()
  611. {
  612.   TASK** thisTask = (TASK**)popData();
  613.   int    newSize = popData();
  614.  
  615.     resizeReturnStack(thisTask, newSize);
  616. }
  617.  
  618.  
  619. /*---------------------------------------------------------------------------*/
  620. /* Memory operations */ 
  621.  
  622. /* @        ( adr -- l ) */
  623. /* fetch the contents of a memory location to data stack */
  624. void pFetch()
  625. {
  626.   int* address = (int*)topData;
  627.   topData = *address;
  628. }
  629.  
  630.  
  631. /* !        ( l adr -- ) */
  632. /* store a value to a certain memory location */
  633. void pStore()
  634. {
  635.   int* address = (int*)popData();
  636.   *address = popData(); 
  637. }
  638.  
  639.  
  640. /* +!        ( l adr -- ) */
  641. /* add a value to a certain memory location */
  642. void pAddStore()
  643. {
  644.   int* address = (int*)popData(); 
  645.   *address += popData();
  646. }
  647.  
  648.  
  649. /* b@        ( adr -- b ) */
  650. /* fetch the contents of a certain byte in memory */
  651. void pBFetch()
  652. {
  653.   char* address = (char*)topData;
  654.   topData = (int)(*address & 0xff);
  655. }
  656.  
  657.  
  658. /* b!        ( b adr -- ) */
  659. /* store a value to a certain byte in memory */
  660. void pBStore()
  661. {
  662.   char* address = (char*)popData(); 
  663.   *address = (char)popData(); 
  664. }
  665.  
  666.  
  667. /* b+!        ( b adr -- ) */
  668. /* add a value to a certain byte in memory */
  669. void pBAddStore()
  670. {
  671.   char* address = (char*)popData(); 
  672.   *address += (char)popData();
  673. }
  674.  
  675.  
  676. /* w@        ( adr -- w ) */
  677. /* fetch the contents of a certain word (16 bits) in memory */
  678. void pWFetch()
  679. {
  680.   short* address = (short*)topData;
  681.   topData = (int)(*address & 0xffff);
  682. }
  683.  
  684.  
  685. /* w!        ( w adr -- ) */
  686. /* store a value to a certain word (16 bits) in memory */
  687. void pWStore()
  688. {
  689.   short* address = (short*)popData(); 
  690.   *address = (short)popData(); 
  691. }
  692.  
  693.  
  694. /* w+!        ( w adr -- ) */
  695. /* add a value to a certain word (16 bits) in memory */
  696. void pWAddStore()
  697. {
  698.   short* address = (short*)popData(); 
  699.   *address += (short)popData();
  700. }
  701.  
  702.  
  703. /* align    ( l -- l ) */
  704. /* given an address, return the address of the next aligned memory location */
  705. void pAlign()
  706. {
  707.   topData = ((topData+CELL-1)/CELL)*CELL;
  708. }
  709.  
  710.  
  711. /* on        ( addr -- ) */
  712. /* set a certain memory location to TRUE (-1) */
  713. void pOn()
  714. {
  715.   int* address = (int*)popData();
  716.   *address = TRUE;
  717. }
  718.  
  719.  
  720. /* off        ( addr -- ) */
  721. /* set a certain memory location to FALSE (0) */
  722. void pOff()
  723. {
  724.   int* address = (int*)popData();
  725.   *address = FALSE;
  726. }
  727.  
  728.  
  729. /* boff        ( addr -- ) */
  730. /* set a certain byte to zero */
  731. void pBOff()
  732. {
  733.   char* address = (char*)popData();
  734.   *address = 0;
  735. }
  736.  
  737.  
  738. /* woff        ( addr -- ) */
  739. /* set a certain word (16 bits) to zero */
  740. void pWOff()
  741. {
  742.   short* address = (short*)popData();
  743.   *address = 0;
  744. }
  745.  
  746.  
  747. /* ++        ( addr -- ) */
  748. /* increment a certain memory location by one */
  749. void pInc()
  750. {
  751.   int* address = (int*)popData();
  752.   (*address)++;
  753. }
  754.  
  755.  
  756. /* cell++        ( addr -- ) */
  757. /* increment a certain memory location by CELL (typically 4) */
  758. void pCellInc()
  759. {
  760.   int** address = (int**)popData();
  761.   (*address)++;
  762. }
  763.  
  764.  
  765. /* --        ( addr -- ) */
  766. /* decrement a certain memory location by one */
  767. void pDec()
  768. {
  769.   int* address = (int*)popData();
  770.   (*address)--;
  771. }
  772.  
  773.  
  774. /* cell--        ( addr -- ) */
  775. /* decrement a certain memory location by CELL (typically 4) */
  776. void pCellDec()
  777. {
  778.   int** address = (int**)popData();
  779.   (*address)--;
  780. }
  781.  
  782.  
  783. /* toggle    ( l adr -- ) */
  784. /* set bits in a certain memory location */
  785. void pToggle()
  786. {
  787.   int* addr = (int*)popData();
  788.   *addr |= popData();
  789. }
  790.  
  791.  
  792. /* untoggle    ( l adr -- ) */
  793. /* clear bits in a certain memory location */
  794. void pUntoggle()
  795. {
  796.   int* addr = (int*)popData();
  797.   *addr &= ~popData();
  798. }
  799.  
  800.  
  801. /* btoggle    ( l adr -- ) */
  802. /* set bits in a certain byte in memory */
  803. void pBToggle()
  804. {
  805.   char* addr = (char*)popData();
  806.   *addr |= (char)popData();
  807. }
  808.  
  809.  
  810. /* buntoggle    ( l adr -- ) */
  811. /* clear bits in a certain byte in memory */
  812. void pBUntoggle()
  813. {
  814.   char* addr = (char*)popData();
  815.   *addr &= ~(char)popData();
  816. }
  817.  
  818.  
  819. /* move        ( adr1 len adr2 -- ) */
  820. /* move a memory region of certain length (in bytes) to another address, */
  821. /* ensuring that no overlapping will occur */
  822. void pMove()
  823. {
  824.   char* target = (char*)popData();
  825.   int n        = popData();
  826.   char* source = (char*)popData();
  827.   char *cp;
  828.  
  829.   /* There was no 'memmove()' standard function in SUN libraries, */
  830.   /* so I had to write one myself */
  831.  
  832.     if (target == source || n <= 0) return;
  833.  
  834.     if (target < source) {
  835.         for (cp = target; n--;) *cp++ = *source++;
  836.     }
  837.     else {
  838.         source += n;
  839.         for (cp = target + n; n--;) *--cp = *--source;
  840.     }
  841. }
  842.  
  843.  
  844. /* fill        ( adr len ch -- ) */
  845. /* fill a memory area of certain length (in bytes) with a certain character */
  846. void pFill()
  847. {
  848.   char c = (char)popData();
  849.   int  n = popData();
  850.   char* target = (char*)popData();
  851.  
  852.     if (n <= 0) return;
  853.     for (; n--;) *target++ = c;
  854. }
  855.  
  856.  
  857. /*---------------------------------------------------------------------------*/
  858. /* String management */
  859.  
  860. /* count    ( adr -- adr len ) */
  861. /* return the length of a null-terminated (ASCIZ) string */
  862. void pCount()
  863. {
  864.   pushData(strlen((char*)topData));
  865. }
  866.  
  867.  
  868. /* match    ( adr1 addr2 -- -1 <OR> 0 <OR> 1 ) */
  869. /* compare two ASCIZ strings */
  870. void pMatch()
  871. {
  872.   char* addr2 = (char*)popData();
  873.   char* addr1 = (char*)topData;
  874.   topData = strcmp(addr1, addr2);
  875. }
  876.  
  877.  
  878. /* scan        ( addr char -- addr ) */
  879. /* Find first matching character starting from an address */
  880. /* Scan until found or end of string (null char) */
  881. void pScan()
  882. {
  883.   char c     = (char)popData();
  884.   char* address = (char*)topData;
  885.  
  886.   while(*address != c && *address) address++;
  887.   topData = (int)address;
  888. }    
  889.  
  890.  
  891. /* scanWhite    ( addr -- addr ) */
  892. /* Find first whitespace character starting from an address */
  893. /* Scan until found or end of string (null char) */
  894. void pScanWhite()
  895. {
  896.   char* address = (char*)topData;
  897.  
  898.   while (*address != ' ' && *address != '\t' && *address) address++;
  899.   topData = (int)address;
  900. }    
  901.  
  902.  
  903. /* skip        ( addr char -- addr ) */
  904. /* Find first character which is not "char" starting from an address
  905.    and return its address */
  906. void pSkip()
  907. {
  908.   char c     = (char)popData();
  909.   char* address = (char*)topData;
  910.  
  911.   while (*address == c) address++;
  912.   topData = (int)address;
  913. }    
  914.  
  915.  
  916. /* skipWhite        ( addr -- addr ) */
  917. /* Skip all white space characters starting from an address */
  918. void pSkipWhite()
  919. {
  920.   char* address = (char*)topData;
  921.  
  922.   while (*address == ' ' || *address == '\t') address++;
  923.   topData = (int)address;
  924. }    
  925.  
  926.  
  927. /* enclose        ( addr char --  ) */
  928. /* Find first matching character starting from an address */
  929. /* and replace that character by a zero (thus forming an */
  930. /* ASCIZ string). */
  931. void pEnclose()
  932. {
  933.   char c     = (char)popData();
  934.   char* address = (char*)popData();
  935.  
  936.   while (*address != c && *address) address++;
  937.   *address = 0;
  938. }    
  939.  
  940.  
  941. /*---------------------------------------------------------------------------*/
  942. /* Arithmetics */
  943.  
  944. /* +          ( l1 l2 -- l1+l2 ) */
  945. /* add two topmost data stack items */
  946. void pPlus()
  947. {
  948.   topData = popData() + topData;
  949. }
  950.  
  951.  
  952. /* -           ( l1 l2  -- l1-l2 ) */
  953. /* subtract the topmost item in the data stack from the second topmost one */
  954. void pMinus()
  955. {
  956.   int temp = popData();
  957.   topData -= temp;
  958. }
  959.  
  960.  
  961. /* *           ( l1 l2 -- l1*l2 ) */
  962. /* multiply two topmost items in the data stack */
  963. void pMultiply()
  964. {
  965.   topData = popData() * topData;
  966. }
  967.  
  968.  
  969. /* /         ( l1 l2 -- l1/l2 ) */
  970. /* divide the second topmost item in the datastack by the topmost one */
  971. void pDivide()
  972. {
  973.   int temp = popData();
  974.   if (!temp) {
  975.       ownPrintf("-- Division by zero");
  976.       execute((*up)->errorVector);
  977.   }
  978.   else topData /= temp;
  979. }
  980.  
  981.  
  982. /* mod        ( l1 l2 -- mod(l1/l2) ) */
  983. /* save as '/', but return modulus instead */
  984. void pModulo()
  985. {
  986.   int temp = popData();
  987.   topData %= temp;
  988. }
  989.  
  990.  
  991. /* /mod        ( l l -- mod quot ) */
  992. /* same as '/' or 'mod', but return both modulus and quotient */
  993. void pDivMod()
  994. {
  995.   int divisor = topData;
  996.   int dividend = secondData;
  997.   secondData = dividend % divisor; 
  998.   topData = dividend / divisor;
  999. }
  1000.  
  1001.  
  1002. /* u/        ( l1 l2 -- l1/l2 ) */
  1003. /* unsigned division */
  1004. void pUDivide()
  1005. {
  1006.   unsigned temp = popData();
  1007.   topData /= temp;
  1008. }
  1009.  
  1010.  
  1011. /* umod        ( l1 l2 -- umod(l1/l2) ) */
  1012. /* unsigned modulus */
  1013. void pUModulo()
  1014. {
  1015.   unsigned temp = popData();
  1016.   topData %= temp;
  1017. }
  1018.  
  1019.  
  1020. /* u/mod    ( l1 l2 -- mod quot ) */
  1021. /* unsigned modulus and division */
  1022. void pUDivMod()
  1023. {
  1024.   unsigned divisor = topData;
  1025.   unsigned dividend = secondData;
  1026.   secondData = dividend % divisor; 
  1027.   topData = dividend / divisor;
  1028. }
  1029.  
  1030.  
  1031. /* 1+       ( l -- l+1 ) */
  1032. /* add one to the topmost item in the data stack */
  1033. void pAdd1()
  1034. {
  1035.   topData += 1;
  1036. }
  1037.  
  1038.  
  1039. /* 2+       ( l -- l+2 ) */
  1040. /* add two to the topmost item in the data stack */
  1041. void pAdd2()
  1042. {
  1043.   topData += 2;
  1044. }
  1045.  
  1046.  
  1047. /* CELL+       ( l -- l+CELL ) */
  1048. /* add CELL to the topmost item in the data stack */
  1049. void pAddCell()
  1050. {
  1051.   topData += CELL;
  1052. }
  1053.  
  1054.  
  1055. /* 1-          ( l -- l-1 ) */
  1056. /* subtract one from the topmost item in the data stack */
  1057. void pSub1()
  1058. {
  1059.   topData -= 1;
  1060. }
  1061.  
  1062.  
  1063. /* 2-       ( l -- l-2 ) */
  1064. /* subtract two from the topmost item in the data stack */
  1065. void pSub2()
  1066. {
  1067.   topData -= 2;
  1068. }
  1069.  
  1070.  
  1071. /* CELL-       ( l -- l-CELL ) */
  1072. /* subtract CELL from the topmost item in the data stack */
  1073. void pSubCell()
  1074. {
  1075.   topData -= CELL;
  1076. }
  1077.  
  1078.  
  1079. /* 2*       ( l1 -- l1*2 ) */
  1080. /* multiply the topmost item in the data stack by two */
  1081. void pMul2()
  1082. {
  1083.   topData *= 2;
  1084. }
  1085.  
  1086.  
  1087. /* 2/        ( l1 -- l1/2 ) */
  1088. /* divide the topmost item in the data stack by two */
  1089. void pDiv2()
  1090. {
  1091.   topData /= 2;
  1092. }
  1093.  
  1094.  
  1095. /* CELL*       ( l1 -- l1*CELL ) */
  1096. /* multiply the topmost item in the data stack by CELL */
  1097. void pMulCell()
  1098. {
  1099.   topData *= CELL;
  1100. }
  1101.  
  1102.  
  1103. /* CELL/        ( l1 -- l1/CELL) */
  1104. /* divide the topmost item in the data stack by CELL */
  1105. void pDivCell()
  1106. {
  1107.   topData /= CELL;
  1108. }
  1109.  
  1110.  
  1111. /* abs        ( l -- l ) */
  1112. /* absolute value the topmost item in the data stack */
  1113. void pAbs()
  1114. {
  1115.   topData = abs(topData);
  1116. }
  1117.  
  1118.  
  1119. /* negate  +/-        ( l -- -l ) */
  1120. /* negate (two's complement) the topmost item in the data stack */
  1121. void pNegate()
  1122. {
  1123.   topData = 0 - topData;
  1124. }
  1125.  
  1126.  
  1127. /* min        ( l l -- l ) */
  1128. /* return the minimum of the two topmost items in the data stack */
  1129. void pMin()
  1130. {
  1131.   int a = popData();
  1132.   int b = topData;
  1133.   topData = (a < b) ? a : b;
  1134. }
  1135.  
  1136.  
  1137. /* max        ( l l -- l ) */
  1138. /* return the maximum of the two topmost items in the data stack */
  1139. void pMax()
  1140. {
  1141.   int a = popData();
  1142.   int b = topData;
  1143.   topData = (a > b) ? a : b;
  1144. }
  1145.  
  1146.  
  1147. /* between    ( l low high -- f ) */
  1148. /* return a flag telling whether a value is between/including certain values */
  1149. void pBetween()
  1150. {
  1151.   int high = popData();
  1152.   int low  = popData();
  1153.   int val  = topData;
  1154.   topData = (val >= low && val <= high) ? TRUE : FALSE;
  1155. }
  1156.  
  1157.  
  1158. /*---------------------------------------------------------------------------*/
  1159. /* Literals */ 
  1160.  
  1161. /* 0        ( -- 0 ) */
  1162. /* load zero to the data stack */
  1163. void pZero()
  1164. {
  1165.   pushData(0);
  1166. }
  1167.  
  1168.  
  1169. /* 1        ( -- 1 ) */
  1170. /* load one to the data stack */
  1171. void pOne()
  1172. {
  1173.   pushData(1);
  1174. }
  1175.  
  1176.  
  1177. /* 2        ( -- 2 ) */
  1178. /* load two to the data stack */
  1179. void pTwo()
  1180. {
  1181.   pushData(2);
  1182. }
  1183.  
  1184.  
  1185. /* CELL        ( -- CELL ) */
  1186. /* load CELL to the data stack */
  1187. void pCell()
  1188. {
  1189.   pushData(CELL);
  1190. }
  1191.  
  1192.  
  1193. /* false    ( -- false ) */
  1194. /* load FALSE (0) to the data stack */
  1195. void pFalse()
  1196. {
  1197.   pushData(FALSE);
  1198. }
  1199.  
  1200.  
  1201. /* true        ( -- true ) */
  1202. /* load TRUE (-1) to the data stack */
  1203. void pTrue()
  1204. {
  1205.   pushData(TRUE);
  1206. }
  1207.  
  1208.  
  1209. /* "immediate"    (  -- ImmedFlag ) */
  1210. /* load the immediate flag to the data stack */
  1211. void pImmedFlag()
  1212. {
  1213.   pushData(ImmedFlag);
  1214. }
  1215.  
  1216.  
  1217. /* "hidden"    (  -- hiddenFlag ) */
  1218. /* load the hidden flag to the data stack */
  1219. void pHiddenFlag()
  1220. {
  1221.   pushData(HiddenFlag);
  1222. }
  1223.  
  1224.  
  1225. /* "smudge"    (  -- SmudgeFlag ) */
  1226. /* load the smudge flag to the data stack */
  1227. void pSmudgeFlag()
  1228. {
  1229.   pushData(SmudgeFlag);
  1230. }
  1231.  
  1232.  
  1233. /* #threads    (  -- #threads ) */
  1234. /* return the number of threads in the hashed dictionary structure */
  1235. void pThreads()
  1236. {
  1237.   pushData(CONTEXTSIZE);
  1238. }
  1239.  
  1240.  
  1241. /* "thisOnly"        (  -- literal ) */
  1242. /* Return a literal denoting that one object only should be modified */
  1243. void pLitThisOnly()
  1244. {
  1245.     pushData(THIS_ONLY);
  1246. }
  1247.  
  1248.  
  1249. /* "wholeFamily"    (  -- literal ) */
  1250. /* Return a literal denoting that whole family should be modified */
  1251. void pLitWholeFamily()
  1252. {
  1253.     pushData(WHOLE_FAMILY);
  1254. }
  1255.  
  1256.  
  1257. /* "derivatives"        (  -- literal ) */
  1258. /* Return a literal denoting that all derivatives should be modified */
  1259. void pLitDerivatives()
  1260. {
  1261.     pushData(DERIVATIVES);
  1262. }
  1263.  
  1264.  
  1265. /*---------------------------------------------------------------------------*/
  1266. /* Conditional tests */ 
  1267.  
  1268. /* 0=         ( l -- f ) */
  1269. /* return true if the topmost item in data stack is zero, false otherwise */
  1270. void pEqual0()
  1271. {
  1272.   topData = (!topData) ? TRUE : FALSE;
  1273. }
  1274.  
  1275.  
  1276. /* 0<>        ( l -- f ) */
  1277. /* return true if the topmost item in data stack is <> 0, false otherwise */
  1278. void pNotEqual0()
  1279. {
  1280.   topData = topData ? TRUE : FALSE;
  1281. }
  1282.  
  1283.  
  1284. /* 0>        ( l -- f ) */
  1285. /* return true if the topmost item in data stack is > 0, false otherwise */
  1286. void pGreater0()
  1287. {
  1288.   topData = (topData > 0) ? TRUE : FALSE;
  1289. }
  1290.  
  1291.  
  1292. /* 0<        ( l -- f ) */
  1293. /* return true if the topmost item in data stack is < 0, false otherwise */
  1294. void pLess0()
  1295. {
  1296.   topData = (topData < 0) ? TRUE : FALSE;
  1297. }
  1298.  
  1299.  
  1300. /* =        ( l l -- f ) */
  1301. /* return true if two topmost items in data stack are equal, false otherwise */
  1302. void pEqual()
  1303.   int temp = popData();
  1304.   topData = (topData == temp) ? TRUE : FALSE;
  1305. }
  1306.  
  1307.  
  1308. /* <>        ( l l -- f ) */
  1309. /* return true if two topmost items in stack are not equal, false otherwise */
  1310. void pNotEqual()
  1311.   int temp = popData();
  1312.   topData = (topData != temp) ? TRUE : FALSE;
  1313. }
  1314.  
  1315.  
  1316. /* <        ( l l -- f ) */
  1317. /* return true if the second topmost item is less than the topmost one */
  1318. void pLess()
  1319. {
  1320.   int temp = popData();
  1321.   topData = (topData < temp) ? TRUE : FALSE;
  1322. }
  1323.  
  1324.  
  1325. /* <=        ( l l -- f ) */
  1326. /* return true if the second topmost item is <= than the topmost one */
  1327. void pLessEq()
  1328. {
  1329.   int temp = popData();
  1330.   topData = (topData <= temp) ? TRUE : FALSE;
  1331. }
  1332.  
  1333.  
  1334. /* >        ( l l -- f ) */
  1335. /* return true if the second topmost item is greater than the topmost one */
  1336. void pGreater()
  1337. {
  1338.   int temp = popData();
  1339.   topData = (topData > temp) ? TRUE : FALSE;
  1340. }
  1341.  
  1342.  
  1343. /* >=        ( l l -- f ) */
  1344. /* return true if the second topmost item is >= than the topmost one */
  1345. void pGreaterEq()
  1346. {
  1347.   int temp = popData();
  1348.   topData = (topData >= temp) ? TRUE : FALSE;
  1349. }
  1350.  
  1351.  
  1352. /* u<        ( l l -- f ) */
  1353. /* same as '<' but unsigned */
  1354. void pULess()
  1355. {
  1356.   unsigned temp = popData();
  1357.   topData = ((unsigned)topData < temp) ? TRUE : FALSE;
  1358. }
  1359.  
  1360.  
  1361. /* u>        ( l l -- f ) */
  1362. /* same as '>' but unsigned */
  1363. void pUGreater()
  1364. {
  1365.   unsigned temp = popData();
  1366.   topData = ((unsigned)topData > temp) ? TRUE : FALSE;
  1367. }
  1368.  
  1369.  
  1370. /*---------------------------------------------------------------------------*/
  1371. /* Logical operations */ 
  1372.  
  1373. /* and        ( l l -- l ) */
  1374. /* return the logical AND of the two topmost items in the data stack */
  1375. void pAnd()
  1376. {
  1377.   int temp = popData();
  1378.   topData &= temp;
  1379. }
  1380.  
  1381.  
  1382. /* or        ( l l -- l ) */
  1383. /* return the logical OR of the two topmost items in the data stack */
  1384. void pOr()
  1385. {
  1386.   int temp = popData();
  1387.   topData |= temp;
  1388. }
  1389.  
  1390.  
  1391. /* xor        ( l l -- l ) */
  1392. /* return the logical XOR of the two topmost items in the data stack */
  1393. void pXor()
  1394. {
  1395.   int temp = popData();
  1396.   topData ^= temp;
  1397. }
  1398.  
  1399.                 
  1400. /* not        ( l -- ~l ) */
  1401. /* return one's complement */
  1402. void pNot()
  1403. {
  1404.   topData = ~topData;
  1405. }
  1406.  
  1407.  
  1408. /* <<        ( l -- l ) */
  1409. /* Shift left */
  1410. void pShiftLeft()
  1411. {
  1412.   topData <<= 1;
  1413. }
  1414.  
  1415.  
  1416. /* >>        ( l -- l ) */
  1417. /* Shift right */
  1418. void pShiftRight()
  1419. {
  1420.   topData >>= 1;
  1421. }
  1422.  
  1423.  
  1424. /*---------------------------------------------------------------------------*/
  1425. /* Control structure primitives */ 
  1426.  
  1427. /* (branch)    (  --  ) */
  1428. /* unconditional branch */
  1429. void pBranch()
  1430. {
  1431.   ip += (int)*ip;
  1432. }
  1433.  
  1434.  
  1435. /* (if)        ( f -- ) */
  1436. /* conditional branch: branch if the topmost item in the data stack is <> 0 */
  1437. void poIf()
  1438. {
  1439.   if (popData()) ip++;
  1440.   else ip += (int)*ip;
  1441. }
  1442.  
  1443.  
  1444. /* (do)        ( high low -- ) */
  1445. /* loop beginning: push loop index and limit to return stack */
  1446. /* if initial index higher than limit, branch */
  1447. void poDo()
  1448. {
  1449.   register int low = popData();
  1450.   register int limit = popData();
  1451.  
  1452.   if (low > limit) ip += (int)*ip;
  1453.   else {
  1454.      pushReturn((int*)(ip+(int)*ip)); /* Push loop exit address (for 'leave') */
  1455.      pushReturn((int*)limit);         /* Push loop index limit */
  1456.      pushReturn((int*)low);             /* Push loop start index */
  1457.      ip++;                             /* Skip the offset */
  1458.   }
  1459. }
  1460.  
  1461.  
  1462. /* (-do)        ( high low -- ) */
  1463. /* loop beginning: push loop index and limit to return stack */
  1464. /* this version does not have initial checks, so it can be used */
  1465. /* for +LOOPs with negative increments */
  1466. void poStraightDo()
  1467. {
  1468.   register int low = popData();
  1469.   register int limit = popData();
  1470.  
  1471.      pushReturn((int*)(ip+(int)*ip)); /* Push loop exit address (for 'leave') */
  1472.      pushReturn((int*)limit);         /* Push loop index limit */
  1473.      pushReturn((int*)low);             /* Push loop start index */
  1474.      ip++;                             /* Skip the offset */
  1475. }
  1476.  
  1477.  
  1478. /* (loop)    ( -- ) */
  1479. /* loop end: if index is greater than limit, end loop */
  1480. /* else increment index by one */
  1481. void poLoop()
  1482. {
  1483.   register int  index = (int)topReturn;
  1484.   register int  limit = (int)secondReturn;
  1485.  
  1486.   if (index < limit) {            /* If index is still below the limit */
  1487.     topReturn=(int*)(index+1); /* Increment index */
  1488.     ip += (int)*ip;         /* and go back to the beginning of the loop */
  1489.   } 
  1490.   else { 
  1491.     nPopReturn(3);        /* Otherwise remove return stack effects */
  1492.     ip++;                /* and continue (skip the address) */
  1493.   }
  1494. }
  1495.  
  1496.  
  1497. /* (+loop)    ( l -- ) */
  1498. /* loop end: if index is greater than limit, end loop */
  1499. /* else increment index by the topmost item in the data stack */
  1500. void poAddLoop()    
  1501. {
  1502. /* This is otherwise the same as (loop) above but index increment 
  1503.    does not necessarily have to be 1 (increment is taken from the 
  1504.    data stack) */
  1505.   register int  incr  = popData();
  1506.   register int  index = (int)topReturn;
  1507.   register int  limit = (int)secondReturn;
  1508.  
  1509.   if (incr > 0) {
  1510.     if (index < limit) {               /* If index is still below the limit */
  1511.         topReturn=(int*)(index+incr); /* Increment index */
  1512.         ip += (int)*ip;                  /* and go back to the beginning of the loop */
  1513.     } 
  1514.     else { 
  1515.         nPopReturn(3);        /* Otherwise remove return stack effects */
  1516.         ip++;                /* and continue (skip the address) */
  1517.     }
  1518.   }
  1519.   else {
  1520.     if (index > limit) {               /* If index is still over the limit */
  1521.         topReturn=(int*)(index+incr); /* Increment index */
  1522.         ip += (int)*ip;                  /* and go back to the beginning of the loop */
  1523.     } 
  1524.     else { 
  1525.         nPopReturn(3);        /* Otherwise remove return stack effects */
  1526.         ip++;                /* and continue (skip the address) */
  1527.     }  
  1528.   }
  1529. }
  1530.  
  1531.  
  1532. /* unloop        (  --  ) */
  1533. /* remove the loop parameters from the return stack */
  1534. /* This operation can be used before forcing an 'exit' from within a DO-loop */
  1535. void pUnloop()
  1536. {
  1537.     nPopReturn(3);
  1538. }
  1539.  
  1540.  
  1541. /* leave    ( -- ) */
  1542. /* Jump to the end of the loop (continue normal execution) */
  1543. void pLeave()
  1544. {
  1545.     /* 
  1546.     Old implementation:
  1547.     topReturn = secondReturn;    Copy limit to index.
  1548.     */
  1549.  
  1550.     /* New implementation */
  1551.     ip = (int**)thirdReturn;    /* Force jump */
  1552.     nPopReturn(3);                /* Remove stack effects */
  1553. }
  1554.  
  1555.  
  1556. /*---------------------------------------------------------------------------*/
  1557. /* Auxiliary system operations */ 
  1558.  
  1559. /* reboot        ( -- ) */
  1560. /* 
  1561.     Empty the return stack and reboot the system starting with the 
  1562.     next operation in the current thread. Note that 'debugTask' will be 
  1563.     reset, because after initializing the return stack, resume operation 
  1564.     would no longer operate correctly.
  1565. */
  1566. void pReboot()
  1567. {
  1568.   OBJECT* bootObj = (OBJECT*)*ip;
  1569.  
  1570.     resetReturn();
  1571.     ip = (int**)bootObj->mfa;
  1572.     debugTask = NIL;
  1573.     ownLongJmp();
  1574. }
  1575.  
  1576.  
  1577. /* This is one of the most important operations in computer programming :-) */
  1578. /* noop        (  --  ) */
  1579. /* do nothing */
  1580. void pNoop()
  1581. { }
  1582.  
  1583.  
  1584. /*---------------------------------------------------------------------------*/
  1585. /* Multitasker primitives */ 
  1586.  
  1587. /* up        (  -- addr ) */
  1588. /* User task area pointer */
  1589. /* Denotes the currently executing task */
  1590. void pUp()
  1591. {
  1592.   pushData((int)&up);
  1593. }
  1594.  
  1595.  
  1596. /* multitasking    (  -- addr ) */
  1597. /* This primitive variable determines whether multitasking is allowed or not */
  1598. pMultitasking()
  1599. {
  1600.   pushData((int)&multitasking);
  1601. }
  1602.  
  1603.  
  1604. /* running    ( task -- flag ) */  
  1605. /* Check if a certain task is currently running (TRUE) or suspended (FALSE) */
  1606. void pRunning()
  1607. {
  1608.   topData = isActivated((TASK**)topData);
  1609. }
  1610.  
  1611.  
  1612. /* #tasks    (  -- number ) */  
  1613. /* How many tasks there are currently in total */
  1614. void pCountTasks()
  1615. {
  1616.   pushData(taskCount);
  1617. }
  1618.  
  1619.  
  1620. /* #running    (  -- number ) */  
  1621. /* How many tasks there are currently running */
  1622. void pCountRunningTasks()
  1623. {
  1624.   pushData(runningCount);
  1625. }
  1626.  
  1627.  
  1628. /* basePriority    (  -- addressOfBasePriority ) */  
  1629. /* How many tasks there are currently running */
  1630. void pBasePriority()
  1631. {
  1632.   pushData((int)&basePriority);
  1633. }
  1634.  
  1635.  
  1636. /* taskingMode    (  -- mode ) */  
  1637. /* return FALSE if the multitasking is preemptive */
  1638. void pMtaskMode()
  1639. {
  1640.   pushData(mtaskMode);
  1641. }
  1642.  
  1643.  
  1644. /* preemptive    (  --  ) */
  1645. /* Set preemptive multitasking mode */
  1646. pPreemptive()
  1647. {
  1648.     if (mtaskMode != PREEMPTIVE) longjmp(p_inner, TRUE);
  1649. }
  1650.  
  1651.  
  1652. /* cooperative     (  --  ) */
  1653. /* Set cooperative multitasking mode */
  1654. pCooperative()
  1655. {
  1656.     if (mtaskMode != COOPERATIVE) cooperativeInterpreter();
  1657. }
  1658.  
  1659.  
  1660. /* <|    (  --  ) */
  1661. /* disable multitasking (starts a critical region) */
  1662. pIOff()
  1663. {
  1664.     if (!inProtRegion) mtStore = multitasking;
  1665.     inProtRegion++;
  1666.     multitasking = FALSE;
  1667. }
  1668.  
  1669.  
  1670. /* |>    (  --  ) */
  1671. /* enable multitasking (ends a critical region). Does 'yield' automatically */
  1672. pIOn()
  1673. {
  1674.     if (inProtRegion > 0) {
  1675.         if (--inProtRegion == 0) {
  1676.             multitasking = mtStore;
  1677.               yield();
  1678.         }
  1679.     }
  1680. }
  1681.  
  1682.  
  1683. /* activate    ( task --  ) */
  1684. /* Activate a task (allow the task to continue its previous execution) */
  1685. void pActivate()
  1686. {
  1687.     /* See 'tasks.c' */
  1688.     activateTask((TASK**)popData());
  1689. }
  1690.  
  1691.  
  1692. /* suspend    ( task --  ) */
  1693. /* Suspend a task (cancel its execution until it is reactivated) by */
  1694. /* removing it from the round-robin chain. This operation operates */
  1695. /* only if the task is in the round-robin chain, and the task is */
  1696. /* not the only running task in the system (because otherwise */
  1697. /* the system would die). */ 
  1698. void pSuspend()
  1699. {
  1700.     suspendTask((TASK**)popData());
  1701. }
  1702.     
  1703.  
  1704. /* does        ( operation task -- ) */  
  1705. /* Reset the behavior of a task. The task must be suspended. */
  1706. void pTaskDoes()
  1707. {
  1708.   TASK**  newTask  = (TASK**)popData();
  1709.   OBJECT* bootOper = (OBJECT*)popData();
  1710.  
  1711.     setTaskBehavior(newTask, bootOper);
  1712. }
  1713.  
  1714.  
  1715. /* <buildBGTask>    (  -- task ) */  
  1716. /* Create a new background task by copying the current one */
  1717. /* The task shares the window with its creator */
  1718. void pBuildBGTask()
  1719. {
  1720.     pushData((int)buildTask());
  1721. }
  1722.  
  1723.  
  1724. /* <deleteTask>    ( task --  ) */
  1725. /* Delete a task provided that it is not running */
  1726. void pDeleteTask()
  1727. {
  1728.     if (!deleteTask((TASK**)popData()))
  1729.         fprintf(confile, "== Cannot delete the only active task in the system ==\n");
  1730. }
  1731.  
  1732.  
  1733. /* <killTask>    ( task --  ) */
  1734. /* 
  1735.     This is a stronger version of <deleteTask> which will delete a task
  1736.     even if the task was current active.
  1737. */
  1738. void pKillTask()
  1739. {
  1740.     if (!killTask((TASK**)popData()))
  1741.         fprintf(confile, "== Cannot kill the only active task in the system ==\n");
  1742. }
  1743.  
  1744.  
  1745. /* raisePriority     ( task --  ) */
  1746. /* Multiply (raise) the priority of the requested task by two */
  1747. void pRaisePriority()
  1748. {
  1749.   TASK** thisTask = (TASK**)popData();
  1750.   (*thisTask)->priority *= 2;
  1751. }
  1752.  
  1753.  
  1754. /* lowerPriority     ( task --  ) */
  1755. /* Divide (lower) the priority of the requested task by two */
  1756. /* Don't do to zero priority, though */
  1757. void pLowerPriority()
  1758. {
  1759.   TASK** thisTask = (TASK**)popData();
  1760.   int pr = (*thisTask)->priority;
  1761.   if (pr && pr > 1) (*thisTask)->priority /= 2;
  1762.   else (*thisTask)->priority = 1;
  1763. }
  1764.  
  1765.  
  1766. /* resetPriorities     (  --  ) */
  1767. /* Reset the priority of all the tasks to 'basePriority' */
  1768. void pResetPriorities()
  1769. {
  1770.   TASK** thisTask = firstTask;
  1771.   
  1772.     fprintf(confile, "== Setting the priority of all tasks to %d (current base priority) ==\n",
  1773.               basePriority);
  1774.               
  1775.     while(thisTask) {
  1776.           (*thisTask)->priority = basePriority;
  1777.           thisTask = (*thisTask)->nextTask;
  1778.     }
  1779. }
  1780.  
  1781.  
  1782. /* 
  1783.    These special stack operations are needed to allow the data and context
  1784.    stacks of tasks to be initialized from other tasks.
  1785. */
  1786.  
  1787. /* >taskData    ( data task -- ) */
  1788. /* Push a value to another task's data stack */
  1789. void pToTaskData()
  1790. {
  1791.   TASK** targetTask = (TASK**)popData();
  1792.   int data = popData();
  1793.  
  1794.     toTaskData(targetTask, data);
  1795. }
  1796.  
  1797.  
  1798. /* >taskReturn    ( data task -- ) */
  1799. /* Push a value to another task's return stack */
  1800. /* The task must not be active at the moment */
  1801. void pToTaskReturn()
  1802. {
  1803.   TASK** targetTask = (TASK**)popData();
  1804.   int data = popData();
  1805.  
  1806.     toTaskReturn(targetTask, data);
  1807. }
  1808.  
  1809.  
  1810. /* >taskContext    ( data task -- ) */
  1811. /* Push a value to another task's context stack */
  1812. /* The task must not be active at the moment */
  1813. void pToTaskCtxt()
  1814. {
  1815.   TASK** targetTask = (TASK**)popData();
  1816.   int data = popData();
  1817.  
  1818.     toTaskCtxt(targetTask,data);
  1819. }
  1820.     
  1821.  
  1822. /*---------------------------------------------------------------------------*/
  1823. /* Context (dictionary) management */ 
  1824.  
  1825. /* searchThis    ( str contextObj -- pair TRUE <or> FALSE ) */
  1826. /* Search if a certain name can be found in a certain context */
  1827. void pSearchThis()
  1828. {
  1829.   OBJECT* ctxtObj = (OBJECT*)popData();
  1830.   char*   str     = (char*)popData(); 
  1831.   PAIR*   pair;
  1832.  
  1833.     pushData((int)(pair = findPairInThis(getContext(ctxtObj), str)));
  1834.     if (pair) pushData(TRUE);
  1835. }
  1836.  
  1837.  
  1838. /* search    ( str -- pair TRUE <or> FALSE ) */
  1839. /* Search if a certain name can be found in the predefined search path */
  1840. void pSearch()
  1841. {
  1842.   char*   str     = (char*)popData(); 
  1843.   PAIR*   pair;
  1844.  
  1845.     pushData((int)(pair = findPairBackward(str)));
  1846.     if (pair) pushData(TRUE);
  1847. }
  1848.  
  1849.  
  1850. /* immediate?    ( pair -- TRUE/FALSE ) */
  1851. /* check if a certain name is designated immediate */
  1852. void pQImmed()
  1853. {
  1854.   PAIR* pair = (PAIR*)topData;
  1855.   topData = (pair->ffa & ImmedFlag) > 0 ? TRUE : FALSE;
  1856.  
  1857.  
  1858. /*---------------------------------------------------------------------------*/
  1859. /* Number management */ 
  1860.  
  1861. /* number    ( addr -- number TRUE <or> FALSE ) */
  1862. /* check if the string in an address is a valid decimal, octal or hex number */
  1863. void pNumber()
  1864. {
  1865.   char* addr = (char*)topData;
  1866.  
  1867.   char*  temp;
  1868.   char** endPtr = &temp;
  1869.  
  1870.   int result = strtol(addr, endPtr, 0);
  1871.   if (!**endPtr) {
  1872.     topData = result;
  1873.     pushData(TRUE);
  1874.   }
  1875.   else topData = FALSE;
  1876. }
  1877.  
  1878.  
  1879. /*---------------------------------------------------------------------------*/
  1880. /* Implementation structure management primitives */
  1881.  
  1882. /* <buildContext> ( object -- context ) */
  1883. /* build a new context and return its address */
  1884. /* The first member of the clone family will be 'object' */
  1885. void pBuildCtxt()
  1886. {
  1887.   OBJECT* object = (OBJECT*)topData; 
  1888.   CONTEXT* context = createContext();
  1889.   addToList(context->cloneFamily, object);
  1890.   topData = (int)context;
  1891. }
  1892.  
  1893.  
  1894. /* <buildName>    ( straddr contextObject -- pair ) */
  1895. /* build a name part and include it in a context */
  1896. void pBuildPair()
  1897. {
  1898.   OBJECT* ctxtObj = (OBJECT*)popData();
  1899.   char* name = (char*)popData();
  1900.   char* newName;
  1901.   newName = allocStrCpy(name);
  1902.   pushData((int)addPair(getContext(ctxtObj), newName, NIL)); 
  1903. }
  1904.  
  1905.  
  1906. /* <buildObject>    ( size -- object ) */
  1907. /* build a new object of given size, initializing its memory to zeros */
  1908. void pBuildObj()
  1909. {
  1910.   int size = popData();
  1911.   pushData((int)createClosure(size));
  1912. }  
  1913.  
  1914.  
  1915. /* <mkdir>    (  -- object ) */
  1916. /* build a new object-oriented object with a clone family */
  1917. /* the only member of the clone family will be the object itself */
  1918. void pBuildDir()
  1919. {
  1920.   OBJECT* object = createClosure(2);
  1921.   CONTEXT* context = createContext();
  1922.   object->mfa->efa = (int*)oContext;
  1923.   object->mfa->pfa = (int*)context;
  1924.   addToList(context->cloneFamily, object);
  1925.   pushData((int)object);  
  1926. }  
  1927.  
  1928.  
  1929. /* <buildStore>        ( size -- store ) */
  1930. /* build a new storage part of an object, initialized to zeros */
  1931. void pBuildStore()
  1932. {
  1933.   int size = popData();
  1934.   pushData((int)createStore(size));
  1935. }  
  1936.  
  1937.  
  1938. /* <buildString>    ( straddr -- straddr ) */
  1939. /* allocate a string */
  1940. void pBuildStr()
  1941. {
  1942.   char* addr = (char*)popData();
  1943.   pushData((int)allocStrCpy(addr));
  1944. }  
  1945.  
  1946.  
  1947. /* <deleteName>        ( pair --  ) */
  1948. /* remove a name from its context */
  1949. void pDeleteName()
  1950. {
  1951.   PAIR* pair = (PAIR*)popData();
  1952.   
  1953.     unlinkPair(pair);
  1954.     free(pair);
  1955. }  
  1956.  
  1957.  
  1958. /* <renameName>        ( pair newNameString --  ) */
  1959. /* rename a pair */
  1960. void pRenameName()
  1961. {
  1962.   char* newName = (char*)popData();
  1963.   PAIR* pair    = (PAIR*)popData();
  1964.  
  1965.     renamePair(pair, newName);
  1966. }
  1967.  
  1968.  
  1969. /* <shallowCopy>        ( oldObject -- newObject ) */
  1970. /* shallow copy an existing OOP object */
  1971. void pShallowCopyObj()
  1972. {
  1973.     topData = (int)cloneObject((OBJECT*)topData);
  1974. }
  1975.  
  1976.  
  1977. /* <derive>            ( object --  ) */
  1978. /* ensure the individuality of the OOP object before the object is modified */
  1979. /* by duplicating its context if there are multiple copies of the object */
  1980. void pDeriveObject()
  1981. {
  1982.     deriveObject((OBJECT*)popData());
  1983. }
  1984.  
  1985.  
  1986. /* <resize>        ( newsize object -- ) */
  1987. /* resize an existing object. If new size is more than old size, */
  1988. /* the newly allocated extra memory is initialized to zeros */
  1989. /* Size are given in CELLs */
  1990. void pResizeObj()
  1991. {
  1992.   OBJECT* object = (OBJECT*)popData();
  1993.   int newsize = popData();
  1994.  
  1995.     resizeClosure(object, newsize);
  1996. }
  1997.  
  1998.  
  1999. /* <expand>        ( more object -- ) */
  2000. /* expand the size of an existing object, initializing the extra memory to 0 */
  2001. /* Size is given in CELLs */
  2002. void pExpandObj()
  2003. {
  2004.   OBJECT* object = (OBJECT*)popData();
  2005.   int more = popData();
  2006.  
  2007.     if (more > 0) resizeClosure(object, object->sfa+more);
  2008. }
  2009.  
  2010.  
  2011. /* <expandFamily>        ( more object -- ) */
  2012. /* expand the size of all the objects in the clone family of the given object */
  2013. /* initializing the extra memory to 0 */
  2014. void pExpandFamily()
  2015. {
  2016.   OBJECT* object = (OBJECT*)popData();
  2017.   int more = popData();
  2018.  
  2019.     if (more > 0) resizeFamilyMembers(object, object->sfa+more);
  2020. }
  2021.  
  2022.  
  2023. /* <optimize>        ( object -- ) */
  2024. /* optimize the memory consumption of an object by removing all the trailing */
  2025. /* zeros from its end. This op should be used for closure objects only */
  2026. void pOptimizeObj()
  2027. {
  2028.   OBJECT* object = (OBJECT*)popData();
  2029.   int     size = object->sfa;
  2030.   int*     addr = (int*)object->mfa + size - 1;
  2031.  
  2032.     /* If primitive, do nothing */
  2033.     if (size == 0) return;
  2034.  
  2035.     while (!*addr) addr--;
  2036.     size = addr - (int*)object->mfa + 1;
  2037.  
  2038.     if (size > 0) resizeClosure(object, size);
  2039. }
  2040.  
  2041.  
  2042. /* <dispose>        ( object --  ) */
  2043. /* dispose of OOP object by removing it from its clone family */
  2044. /* and by deallocating its storage space */ 
  2045. void pDisposeObject()
  2046. {
  2047.   OBJECT* object = (OBJECT*)popData();
  2048.   WindowPtr browserWindow;
  2049.  
  2050.     /*
  2051.         Remove the object from its clone family, deleting the clone family 
  2052.         and reorganizing the family hierarchy if needed.
  2053.     */
  2054.     removeFromItsFamily(object);
  2055.     
  2056.     /* yyy warning: the code below is non-portable */
  2057.     /* To ensure integrity, we must close the possible browser to this object */
  2058.     browserWindow = findBrowser(object);
  2059.     if (browserWindow) deleteBrowser(browserWindow);
  2060.  
  2061.     free(object);
  2062. }
  2063.  
  2064.  
  2065. /* <free>    ( addr -- ) */
  2066. /* Free heap memory (this is the same as 'free' in C */
  2067. void pFree()
  2068. {
  2069.     free((void*)popData());
  2070. }
  2071.  
  2072.  
  2073. /* <freeStore>     ( object --  ) */
  2074. /* Free the store part of an object, provided that the object is not a primitive */
  2075. /* (primitives do not have a store part) */
  2076. void pFreeStore()
  2077. {
  2078.   OBJECT* object = (OBJECT*)popData();
  2079.  
  2080.     if (object->sfa) free(object->mfa);
  2081. }
  2082.  
  2083.  
  2084. /* <recompile>        ( oldProperty changedPair --  ) */
  2085. /* starting from a (changed) pair, rebind all the references to the */
  2086. /* old property in the corresponding object to the new property */
  2087. void pRecompile()
  2088. {
  2089.   PAIR* changedPair = (PAIR*)popData();
  2090.   OBJECT* oldProperty = (OBJECT*)popData();
  2091.   
  2092.       recompileProperty(changedPair, oldProperty);
  2093. }
  2094.  
  2095.  
  2096. /* <rebind>        ( fromPair --  ) */
  2097. /* starting from the given pair, check the early bindings and */
  2098. /* rebind if necessary */
  2099. void pRebind()
  2100. {
  2101.   PAIR* fromPair = (PAIR*)popData();
  2102.   
  2103.       rebindContext(fromPair, NIL, NIL);
  2104. }
  2105.  
  2106.  
  2107. /* <reorganize>        ( whoToModify object --  ) */
  2108. /* Notify the system that the given object has changed, and its location */
  2109. /* in the clone family hierarchy must be taken into reconsideration */
  2110. void pReorganize()
  2111. {
  2112.   OBJECT* object = (OBJECT*)popData();
  2113.   int whoToModify = popData();
  2114.  
  2115.     confirmObjectType(object, whoToModify, REMOVING_SOMETHING);
  2116. }  
  2117.  
  2118.  
  2119. /* <rePair>    ( pair object -- pair ) */
  2120. /* This is a temporary implementation:
  2121.     Since 'pair' may no longer be in the context of 'object' after executing
  2122.     <derive>, we must find the first pair in 'object's context with the same
  2123.     ofa field as in 'pair'.
  2124. */
  2125. void pRePair()
  2126. {
  2127.   OBJECT* object = (OBJECT*)popData();
  2128.   PAIR*   pair = (PAIR*)topData;
  2129.  
  2130.   CONTEXT* context = getContext(object);
  2131.   OBJECT* target = pair->ofa;
  2132.   PAIR* thisPair = context->firstPair;
  2133.  
  2134.     while (thisPair) {
  2135.         if (thisPair->ofa == target) {
  2136.             topData = (int)thisPair;
  2137.             return;
  2138.         }
  2139.         thisPair = thisPair->sfa;
  2140.     }
  2141.     
  2142.     topData = NIL;
  2143.       fprintf(confile, "== Integrity error detected: pair not found in '<rePair>' ==\n");
  2144.     reportIntegrityError();
  2145.     ownLongJmp();
  2146. }
  2147.     
  2148.  
  2149. /*---------------------------------------------------------------------------*/
  2150. /* Implementation structure offsets */
  2151.  
  2152. /* name>object    ( pair -- object ) */
  2153. /* given a name part, return the identity of the corresponding object */
  2154. void pPairToObj()
  2155. {
  2156.   PAIR* pair = (PAIR*)topData;
  2157.   topData = (int)pair->ofa;
  2158. }
  2159.  
  2160.  
  2161. /* name'object    ( pair -- ofa ) */
  2162. /* return the address of the 'object' (OFA) field in a name part */
  2163. void pPairOFA()
  2164. {
  2165.   PAIR* pair = (PAIR*)topData;
  2166.   topData = (int)&pair->ofa;
  2167. }
  2168.  
  2169.  
  2170. /* name'name    ( pair -- nfa ) */
  2171. /* return the address of the 'name' (NFA) field in a name part */
  2172. void pPairNFA()
  2173. {
  2174.   PAIR* pair = (PAIR*)topData;
  2175.   topData = (int)&pair->nfa;
  2176. }
  2177.  
  2178.  
  2179. /* name'flags    ( pair -- ffa ) */
  2180. /* return the address of the 'flags' (FFA) field in a name part */
  2181. void pPairFFA()
  2182. {
  2183.   PAIR* pair = (PAIR*)topData;
  2184.   topData = (int)&pair->ffa;
  2185. }
  2186.  
  2187.  
  2188. /* name'prev    ( pair -- lfa ) */
  2189. /* return the address of the 'prev' (LFA) field in a name part */
  2190. void pPairLFA()
  2191. {
  2192.   PAIR* pair = (PAIR*)topData;
  2193.   topData = (int)&pair->lfa;
  2194. }
  2195.  
  2196.  
  2197. /* name'succ    ( pair -- lfa ) */
  2198. /* return the address of the 'succ' (SFA) field in a name part */
  2199. void pPairSFA()
  2200. {
  2201.   PAIR* pair = (PAIR*)topData;
  2202.   topData = (int)&pair->sfa;
  2203. }
  2204.  
  2205.  
  2206. /* name'context    ( pair -- cfa ) */
  2207. /* return the address of the 'context' (CFA) field in a name part */
  2208. void pPairCFA()
  2209. {
  2210.   PAIR* pair = (PAIR*)topData;
  2211.   topData = (int)&pair->cfa;
  2212. }
  2213.  
  2214.  
  2215. /* object>name    ( object -- pair TRUE <OR> FALSE ) */
  2216. /* given an object, return the possible corresponding name part */
  2217. void pObjToPair()
  2218. {
  2219.   OBJECT* object = (OBJECT*)topData;
  2220.   PAIR* pair;
  2221.  
  2222.   topData = (int)(pair = findNameBackward(object));
  2223.   if (pair) pushData(TRUE);
  2224. }
  2225.  
  2226.  
  2227. /* object>typename    ( object -- pair TRUE <OR> FALSE ) */
  2228. /* given an OOP object, return the first possible corresponding name part */
  2229. /* which refers to the same context as the given object. This can be */
  2230. /* regarded as the "type" of that OOP object. */
  2231. void pObjToTypeName()
  2232. {
  2233.   OBJECT* ctxtObject = (OBJECT*)topData;
  2234.   PAIR* pair;
  2235.  
  2236.   topData = (int)(pair = findTypeForward(ctxtObject));
  2237.   if (pair) pushData(TRUE);
  2238. }
  2239.  
  2240.  
  2241. /* object>store    ( object -- store ) */
  2242. /* given an object, return the address of its store part */
  2243. void pObjToStore()
  2244. {
  2245.   OBJECT* object = (OBJECT*)topData;
  2246.   topData = (int)object->mfa;
  2247. }
  2248.  
  2249.  
  2250. /* object'store    ( object -- mfa ) */
  2251. /* return the address of the 'store' (MFA) field in an object header */
  2252. void pObjectMFA()
  2253. {
  2254.   OBJECT* object = (OBJECT*)topData;
  2255.   topData = (int)&object->mfa;
  2256. }
  2257.  
  2258.  
  2259. /* object'size    ( object -- sfa ) */
  2260. /* return the address of the 'size' (SFA) field in an object header */
  2261. void pObjectSFA()
  2262. {
  2263.   OBJECT* object = (OBJECT*)topData;
  2264.   topData = (int)&object->sfa;
  2265. }
  2266.  
  2267.  
  2268. /* object>context    ( contextObject -- context ) */
  2269. /* return the context of the given OOP object */
  2270. /* ensuring that the object really is a valid OOP object */
  2271. /* with its own context. */
  2272. void pObjToContext()
  2273. {
  2274.   OBJECT* object = (OBJECT*)topData;
  2275.  
  2276.     if (!isContextObject(object)) {
  2277.         ownPrintf("-- Invalid parameter received by 'object>context'");
  2278.         execute((*up)->errorVector);
  2279.     }
  2280.     else topData = (int)getContext(object);
  2281. }
  2282.  
  2283.  
  2284. /* context'thread    ( thread context -- pairAddr ) */
  2285. /* return the name referred to from the n'th thread in a context */
  2286. /* Indexing starts from zero */
  2287. void pContextThread()
  2288. {
  2289.   CONTEXT* context  = (CONTEXT*)popData();
  2290.   int thread = topData;
  2291.  
  2292.     topData = (int)&(context->lastPair[thread]);
  2293. }
  2294.  
  2295.  
  2296. /* context'first    ( context -- pairAddr ) */
  2297. /* return the first name in a context (beginning of succ link) */
  2298. void pContextFirst()
  2299. {
  2300.   CONTEXT* context = (CONTEXT*)topData;
  2301.   
  2302.     topData = (int)&context->firstPair;
  2303. }
  2304.  
  2305.  
  2306. /* context'latest    ( context -- pairAddr ) */
  2307. /* return the latest defined name in a context */
  2308. void pContextLatest()
  2309. {
  2310.   CONTEXT* context = (CONTEXT*)topData;
  2311.   
  2312.     topData = (int)&context->latestPair;
  2313. }
  2314.  
  2315.  
  2316. /* context'family    ( context -- cloneFamily ) */
  2317. /* this is needed for concatenation-based object-oriented programming: */
  2318. /* return the clone family of the given OOP object */
  2319. /* clone family is represented as a LIST object (lists.c) */
  2320. void pContextFamily()
  2321. {
  2322.   CONTEXT* context = (CONTEXT*)topData;
  2323.   
  2324.     topData = (int)&context->cloneFamily;
  2325. }
  2326.  
  2327.  
  2328. /* context'parents    ( context -- parentFamilyList ) */
  2329. /* return the LIST object containing the parent families of the given OOP object */
  2330. void pContextParents()
  2331. {
  2332.   CONTEXT* context = (CONTEXT*)topData;
  2333.   
  2334.     topData = (int)&context->parentFamilies;
  2335. }
  2336.  
  2337.  
  2338. /* context'children    ( context -- childFamilyList ) */
  2339. /* return the LIST object containing the child families of the given OOP object */
  2340. void pContextChildren()
  2341. {
  2342.   CONTEXT* context = (CONTEXT*)topData;
  2343.   
  2344.     topData = (int)&context->childFamilies;
  2345. }
  2346.  
  2347.  
  2348. /* checkSystemValidity    (  --  ) */
  2349. /* Perform integrity checks for every context in the system */
  2350. /* This allows us to recognize memory leaks, dangling pointers etc. */
  2351. void pCheckSystem()
  2352. {
  2353.   /* The first context in the context list is always 'rootContext' */
  2354.   /* However, since rootContext is so big (= time-consuming to check) */
  2355.   /* we start from the next context */
  2356.   CONTEXT* thisContext = rootContext->nextContext; 
  2357.  
  2358.     while (thisContext) {
  2359.         checkIntegrity(thisContext);
  2360.         thisContext = thisContext->nextContext;
  2361.     }
  2362. }
  2363.  
  2364.  
  2365. /*---------------------------------------------------------------------------*/
  2366. /* Debugging, decompilation, and tracing primitives */ 
  2367. /* Most of these primitives can be found from separate files */
  2368.  
  2369. /* see        ( object -- ) */
  2370. /* decompile the definition of an object */
  2371. void pSee()
  2372. {
  2373.     /* See 'image.c' */
  2374.     decompile((OBJECT*)popData());
  2375.     yield();
  2376. }
  2377.  
  2378.  
  2379. /*---------------------------------------------------------------------------*/
  2380. /* Basic file interface */
  2381.  
  2382. /* "write"    ( -- "write" ) */
  2383. /* return address of a string denoting file "write" mode */
  2384. void pWriteMode()
  2385. {
  2386.   pushData((int)"w");
  2387. }
  2388.  
  2389.  
  2390. /* "append"    ( -- "append" ) */
  2391. /* return address of a string denoting file "append" mode */
  2392. void pAppendMode()
  2393. {
  2394.   pushData((int)"a");
  2395. }
  2396.  
  2397.  
  2398. /* pushInfile    ( string --  ) */
  2399. /* push current input file to the task-specific file stack, and  */
  2400. /* open a new file for reading instead. */
  2401. void pPushInfile()
  2402. {
  2403.   char* fileName = (char*)popData();
  2404.  
  2405.     pushInfile(fileName);
  2406. }
  2407.  
  2408.  
  2409. /* popInfile    (  --  ) */
  2410. /* Close the current input file and return to the previous one */
  2411. /* Do not close 'stdin', though. */
  2412. void pPopInfile()
  2413. {
  2414.     popInfile();
  2415. }
  2416.  
  2417.  
  2418. /* resetInfiles    (  --  ) */
  2419. /* Reset the input file stack. */
  2420. /* Close all the input files except the first. */
  2421. void pResetInfiles()
  2422. {
  2423.     while(infileSp > 0) popInfile();
  2424. }
  2425.  
  2426.  
  2427. /* pushOutfile    ( string mode --  ) */
  2428. /* push current output file to the task-specific file stack, and  */
  2429. /* open a new file for writing or appending instead. */
  2430. void pPushOutfile()
  2431. {
  2432.   char* mode = (char*)popData();
  2433.   char* fileName = (char*)popData();
  2434.  
  2435.     pushOutfile(fileName, mode);
  2436. }
  2437.  
  2438.  
  2439. /* popOutfile    (  --  ) */
  2440. /* Close the current output file and return to the previous one */
  2441. /* Do not close stdout or stderr, though. */
  2442. void pPopOutfile()
  2443. {
  2444.     popOutfile();
  2445. }
  2446.  
  2447.  
  2448. /* resetOutfiles    (  --  ) */
  2449. /* Reset output file stack. */
  2450. /* Close all the output files except the first. */
  2451. void pResetOutfiles()
  2452. {
  2453.     while(outfileSp > 0) popOutfile();
  2454. }
  2455.  
  2456.  
  2457. /* errorTo        (  --  ) */
  2458. /* Push error file to outfile stack. */
  2459. /* This allows a task to print to the screen even though it was */
  2460. /* currently loading a file */
  2461. void pErrfilePush()
  2462. {
  2463.     pushToOFS(errfile);
  2464. }
  2465.  
  2466.  
  2467. /* consoleTo        (  --  ) */
  2468. /* Push console file to outfile stack */
  2469. /* This allows tasks to print to the console window. */
  2470. void pConfilePush()
  2471. {
  2472.     pushToOFS(confile);
  2473. }
  2474.  
  2475.  
  2476. /*---------------------------------------------------------------------------*/
  2477. /* Object-oriented primitives */
  2478.  
  2479. /* self        (  -- self ) */
  2480. /* return self */
  2481. void pSelf()
  2482. {
  2483.   pushData((int)topContext);
  2484. }
  2485.  
  2486.  
  2487. /* &        (  -- self ) */
  2488. /* return the identity of the receiver of the previous message */
  2489. void pPrevSelf()
  2490. {
  2491.   pushData((int)prevContext);
  2492. }
  2493.  
  2494.  
  2495. /* >self    ( object --  ) */
  2496. /* push an item to the context stack */
  2497. void pToSelf()
  2498. {
  2499.   pushContext((int*)popData());
  2500. }
  2501.  
  2502.  
  2503. /* self>    (  -- object ) */
  2504. /* pop an item from the context stack */
  2505. void pSelfFrom()
  2506. {
  2507.   pushData((int)popContext());
  2508. }
  2509.  
  2510.  
  2511. /* self>drop    (  --  ) */
  2512. /* drop an item from the context stack */
  2513. void pSelfDrop()
  2514. {
  2515.   (void)popContext();
  2516. }
  2517.  
  2518.  
  2519. /* cdepth    (  -- l ) */
  2520. /* push the depth of context stack to the top of data stack */
  2521. void pCDepth()
  2522. {
  2523.   pushData(contextSp - contextStackBottom());
  2524. }
  2525.  
  2526.  
  2527. /* .cs        (  --  ) */
  2528. /* print the contents of context stack to outfile */
  2529. /* try to decompile possible object types */
  2530. void pPrintCStack()
  2531. {
  2532.   int* ptr = (int*)contextStackBottom();
  2533.  
  2534.     if (contextSp <= contextStackBottom()) return; 
  2535.  
  2536.     while ((int*)contextSp >= ++ptr) { 
  2537.           PAIR* pair = findTypeForward(*ptr);
  2538.  
  2539.           if (pair) {
  2540.               ownPrintf("%s:", pair->nfa);
  2541.             ownPrintf("%d ", *ptr);
  2542.         }
  2543.         else {
  2544.             pair = findNameForward(*ptr);
  2545.             if (pair) ownPrintf("%s ", pair->nfa);
  2546.             else ownPrintf("%d ", *ptr);
  2547.         }
  2548.     }
  2549. }
  2550.     
  2551.  
  2552. /* resizeContextStack    ( newSize task --  ) */
  2553. /* resize the context stack of the given task */
  2554. void pResizeContext()
  2555. {
  2556.   TASK** thisTask = (TASK**)popData();
  2557.   int    newSize = popData();
  2558.  
  2559.     resizeContextStack(thisTask, newSize);
  2560. }
  2561.  
  2562.  
  2563. /* >send    ( object messageString --  ) */
  2564. /* Send a message to an object */
  2565. /* Note that context stack must be popped after a call to '>send' */
  2566. /* This cannot be done here, because we need to execute threaded code */
  2567. void pSend()
  2568. {
  2569.   char*   string = (char*)popData();
  2570.   OBJECT* object = (OBJECT*)popData();
  2571.   PAIR*   pair = messageLookUp(object, string);
  2572.  
  2573.   pushContext((int*)object);
  2574.  
  2575.   if (pair) execute(pair->ofa);
  2576.   else {
  2577.     fprintf(confile, "== Message binding error."); showTaskID();
  2578.     ownPrintf("-- Cannot bind \"%s\"", string);
  2579.     execute((*up)->errorVector);
  2580.   }
  2581. }
  2582.  
  2583.  
  2584. /* >resend    ( thisPair --  ) */
  2585. /* Resend a message to the current object, starting from 'thisPair' */
  2586. /* This operations is the equivalent of super-reference in Smalltalk */
  2587. /* Unlike Smalltalk, >resend does not take any identifier as an argument */
  2588. /* (previous identifier is used implicitly) */
  2589. void pResend()
  2590. {
  2591.   PAIR* prevPair = (PAIR*)popData();
  2592.   PAIR* superPair = selfLookUp(prevPair->lfa, prevPair->nfa);
  2593.   
  2594.   if (superPair) execute(superPair->ofa);
  2595.   else {
  2596.     fprintf(confile, "== Message binding error."); showTaskID();
  2597.     ownPrintf("-- Cannot bind (resend) \"%s\"", prevPair->nfa);
  2598.     execute((*up)->errorVector);
  2599.   }
  2600. }
  2601.  
  2602.  
  2603. /* respondsTo    ( string object -- flag ) */
  2604. /* Check if the object is capable of answering to the requested message */
  2605. /* (given as a string). Note that the result value is actually not a flag, */
  2606. /* but the address of the found pair (or NIL) */
  2607. void pRespondsTo()
  2608. {
  2609.   OBJECT* object = (OBJECT*)popData();
  2610.   char* message = (char*)popData();
  2611.   
  2612.     pushData((int)respondsTo(object, message));
  2613. }
  2614.  
  2615.  
  2616. /* hasContext    ( object -- flag ) */
  2617. /* Check if the given address is a valid OOP object identity */
  2618. void pHasContext()
  2619. {
  2620.     topData = isContextObject((OBJECT*)topData);
  2621. }
  2622.  
  2623.  
  2624. /* >area        ( object -- addrOfFirstDataSlot )
  2625. /* Return the address of the first data slot of an object */
  2626. /* DATAOFFSET is a macro that tells how many cells each instance has */
  2627. /* before the actual data slots begin */
  2628. pToArea()
  2629. {
  2630.     topData = (int)((int*)((OBJECT*)topData)->mfa + DATAOFFSET);
  2631. }
  2632.  
  2633.  
  2634. /* area0            (  -- addrOfFirstDataSlot ) */
  2635. /* Return the address of the first data slot of the current object */
  2636. pAreaZero()
  2637. {
  2638.     pushData((int)((int*)((OBJECT*)topContext)->mfa + DATAOFFSET));
  2639. }
  2640.  
  2641.  
  2642. /* area#            (  -- sizeOfArea ) */
  2643. /* Return the size of the current object's data area (in cells) */
  2644. pAreaSize()
  2645. {
  2646.     pushData(((OBJECT*)topContext)->sfa - DATAOFFSET);
  2647. }
  2648.  
  2649.  
  2650. /*---------------------------------------------------------------------------*/
  2651. /* InitPrimitives(): initialize the name space (primitive operations) */
  2652.  
  2653. void initPrimitives()
  2654. {
  2655.   /* Execution primitives */
  2656.   addPair(rootContext, "exit",        oExit = createPrimitive(pExit));
  2657.   addPair(rootContext, "freeExit",    createPrimitive(pFreeExit)); hide();
  2658.   addPair(rootContext, "<executeStore>",createPrimitive(pExecStore)); hide();
  2659.   addPair(rootContext, "execute",    createPrimitive(pExecute));
  2660.  
  2661.  
  2662.   /* Data access primitives */
  2663.   addPair(rootContext, "(=sharedVar)",    oSharedVar     = createPrimitive(pSharedVar)); hide();
  2664.   addPair(rootContext, "(=taskVar)",    oTaskVar    = createPrimitive(pTaskVar)); hide();
  2665.   addPair(rootContext, "(=sharedConst)",oSharedConst= createPrimitive(pSharedConst)); hide();
  2666.   addPair(rootContext, "(=taskConst)",  oTaskConst     = createPrimitive(pTaskConst)); hide();
  2667.   addPair(rootContext, "(=context)",    oContext    = createPrimitive(pContext)); hide();
  2668.   addPair(rootContext, "(=REF)",        oREF        = createPrimitive(pREF)); hide();
  2669.   addPair(rootContext, "(=VAR)",        oVAR        = createPrimitive(pVAR)); hide();
  2670.   addPair(rootContext, "(->)",                          createPrimitive(pIncAss)); hide();
  2671.   addPair(rootContext, "(lit)",         oLit         = createPrimitive(pLit)); hide();
  2672.   addPair(rootContext, "(\"lit)",        oStrLit        = createPrimitive(pStrLit)); hide();
  2673.   addPair(rootContext, "(=sharedVector)", createPrimitive(pSharedVector)); hide();
  2674.   addPair(rootContext, "(=taskVector)",    createPrimitive(pTaskVector)); hide();
  2675.  
  2676.  
  2677.   /* Data stack primitives */
  2678.   addPair(rootContext, "dup",         createPrimitive(pDup));
  2679.   addPair(rootContext, "2dup",         createPrimitive(pDup2));
  2680.   addPair(rootContext, "?dup",         createPrimitive(pQDup));
  2681.   addPair(rootContext, "drop",         createPrimitive(pDrop));
  2682.   addPair(rootContext, "2drop",     createPrimitive(pDrop2));
  2683.   addPair(rootContext, "swap",         createPrimitive(pSwap));
  2684.   addPair(rootContext, "2swap",     createPrimitive(pSwap2));
  2685.   addPair(rootContext, "over",         createPrimitive(pOver));
  2686.   addPair(rootContext, "2over",     createPrimitive(pOver2));
  2687.   addPair(rootContext, "rot",         createPrimitive(pRot));
  2688.   addPair(rootContext, "-rot",         createPrimitive(pRor));
  2689.   addPair(rootContext, "nip",         createPrimitive(pNip));
  2690.   addPair(rootContext, "tuck",         createPrimitive(pTuck));
  2691.   addPair(rootContext, "pick",         createPrimitive(pPick));
  2692.   addPair(rootContext, "roll",         createPrimitive(pRoll));
  2693.   addPair(rootContext, "depth",     createPrimitive(pDepth));
  2694.   addPair(rootContext, "resetSp",     createPrimitive(resetData));
  2695.   addPair(rootContext, ".s",        createPrimitive(pPrintStack));
  2696.   addPair(rootContext, "resizeDataStack",createPrimitive(pResizeData));
  2697.  
  2698.  
  2699.   /* Return stack primitives */
  2700.   addPair(rootContext, ">r",        createPrimitive(pToR));
  2701.   addPair(rootContext, "r@",         createPrimitive(pRFetch));
  2702.   addPair(rootContext, "r>",         createPrimitive(pRFrom));
  2703.   addPair(rootContext, "i",         createPrimitive(pI));
  2704.   addPair(rootContext, "j",             createPrimitive(pJ));
  2705.   addPair(rootContext, "rdepth",     createPrimitive(pRDepth));
  2706.   addPair(rootContext, "dup>r",     createPrimitive(pDupToR));
  2707.   addPair(rootContext, "r>drop",     createPrimitive(pRFromDrop));
  2708.   addPair(rootContext, ".rs",        createPrimitive(pPrintRStack));
  2709.   addPair(rootContext, "resizeReturnStack",createPrimitive(pResizeReturn));
  2710.  
  2711.  
  2712.   /* Temporary variable (block) primitives */
  2713.   addPair(rootContext, "({)",        createPrimitive(pOpenFrame));
  2714.   addPair(rootContext, "(})",        createPrimitive(pCloseFrame));
  2715.   addPair(rootContext, "<temp>",    createPrimitive(pAllocTemp));
  2716.   addPair(rootContext, "temp:",        createPrimitive(pAccessTemp));
  2717.  
  2718.  
  2719.   /* Memory primitives */
  2720.   addPair(rootContext, "@",         createPrimitive(pFetch));
  2721.   addPair(rootContext, "!",             createPrimitive(pStore));
  2722.   addPair(rootContext, "+!",        createPrimitive(pAddStore));
  2723.   addPair(rootContext, "b@",        createPrimitive(pBFetch));
  2724.   addPair(rootContext, "b!",         createPrimitive(pBStore));
  2725.   addPair(rootContext, "b+!",         createPrimitive(pBAddStore));
  2726.   addPair(rootContext, "w@",        createPrimitive(pWFetch));
  2727.   addPair(rootContext, "w!",         createPrimitive(pWStore));
  2728.   addPair(rootContext, "w+!",         createPrimitive(pWAddStore));
  2729.   addPair(rootContext, "on",        createPrimitive(pOn));
  2730.   addPair(rootContext, "off",        createPrimitive(pOff));
  2731.   addPair(rootContext, "boff",        createPrimitive(pBOff));
  2732.   addPair(rootContext, "woff",        createPrimitive(pWOff));
  2733.   addPair(rootContext, "++",        createPrimitive(pInc));
  2734.   addPair(rootContext, "cell++",    createPrimitive(pCellInc));
  2735.   addPair(rootContext, "--",        createPrimitive(pDec));
  2736.   addPair(rootContext, "cell--",    createPrimitive(pCellDec));
  2737.   addPair(rootContext, "toggle",     createPrimitive(pToggle));
  2738.   addPair(rootContext, "untoggle",     createPrimitive(pUntoggle));
  2739.   addPair(rootContext, "btoggle",     createPrimitive(pBToggle));
  2740.   addPair(rootContext, "buntoggle", createPrimitive(pBUntoggle));
  2741.   addPair(rootContext, "align",        createPrimitive(pAlign));
  2742.   addPair(rootContext, "move",         createPrimitive(pMove));
  2743.   addPair(rootContext, "fill",         createPrimitive(pFill));
  2744.  
  2745.  
  2746.   /* String primitives */
  2747.   addPair(rootContext, "count",     createPrimitive(pCount));
  2748.   addPair(rootContext, "match",     createPrimitive(pMatch));
  2749.   addPair(rootContext, "scan",         createPrimitive(pScan));
  2750.   addPair(rootContext, "scanWhite", createPrimitive(pScanWhite));
  2751.   addPair(rootContext, "skip",         createPrimitive(pSkip));
  2752.   addPair(rootContext, "skipWhite",    createPrimitive(pSkipWhite));
  2753.   addPair(rootContext, "enclose",    createPrimitive(pEnclose));
  2754.  
  2755.  
  2756.   /* Integer arithmetic primitives */
  2757.   addPair(rootContext, "+",         createPrimitive(pPlus));
  2758.   addPair(rootContext, "-",             createPrimitive(pMinus));
  2759.   addPair(rootContext, "*",            createPrimitive(pMultiply));
  2760.   addPair(rootContext, "/",             createPrimitive(pDivide));
  2761.   addPair(rootContext, "mod",        createPrimitive(pModulo));
  2762.   addPair(rootContext, "/mod",        createPrimitive(pDivMod));
  2763.   addPair(rootContext, "u/",         createPrimitive(pUDivide));
  2764.   addPair(rootContext, "umod",         createPrimitive(pUModulo));
  2765.   addPair(rootContext, "u/mod",     createPrimitive(pUDivMod));
  2766.   addPair(rootContext, "1+",         createPrimitive(pAdd1));
  2767.   addPair(rootContext, "2+",         createPrimitive(pAdd2));
  2768.   addPair(rootContext, "cell+",     createPrimitive(pAddCell));
  2769.   addPair(rootContext, "1-",         createPrimitive(pSub1));
  2770.   addPair(rootContext, "2-",         createPrimitive(pSub2));
  2771.   addPair(rootContext, "cell-",     createPrimitive(pSubCell));
  2772.   addPair(rootContext, "2*",         createPrimitive(pMul2));
  2773.   addPair(rootContext, "2/",         createPrimitive(pDiv2));
  2774.   addPair(rootContext, "cell*",     createPrimitive(pMulCell));
  2775.   addPair(rootContext, "cell/",     createPrimitive(pDivCell));
  2776.   addPair(rootContext, "abs",         createPrimitive(pAbs));
  2777.   addPair(rootContext, "negate",     createPrimitive(pNegate));
  2778.   addPair(rootContext, "+/-",         createPrimitive(pNegate));
  2779.  
  2780.  
  2781.   /* Literal primitives */
  2782.   addPair(rootContext, "zero",        createPrimitive(pZero));
  2783.   addPair(rootContext, "one",         createPrimitive(pOne));
  2784.   addPair(rootContext, "cell",         createPrimitive(pCell));
  2785.   addPair(rootContext, "false",        createPrimitive(pFalse));
  2786.   addPair(rootContext, "true",        createPrimitive(pTrue));
  2787.   addPair(rootContext, "\"write\"",    createPrimitive(pWriteMode));
  2788.   addPair(rootContext, "\"append\"",    createPrimitive(pAppendMode));
  2789.   addPair(rootContext, "\"immediate\"",    createPrimitive(pImmedFlag));
  2790.   addPair(rootContext, "\"hidden\"",    createPrimitive(pHiddenFlag));
  2791.   addPair(rootContext, "\"smudge\"",    createPrimitive(pSmudgeFlag));
  2792.   addPair(rootContext, "#threads",    createPrimitive(pThreads));
  2793.   addPair(rootContext, "\"thisOnly\"",createPrimitive(pLitThisOnly)); hide();
  2794.   addPair(rootContext, "\"wholeFamily\"",createPrimitive(pLitWholeFamily)); hide();
  2795.   addPair(rootContext, "\"derivatives\"",createPrimitive(pLitDerivatives)); hide();
  2796.  
  2797.  
  2798.   /* Comparison primitives */
  2799.   addPair(rootContext, "0=",         createPrimitive(pEqual0));
  2800.   addPair(rootContext, "0<>",         createPrimitive(pNotEqual0));
  2801.   addPair(rootContext, "0<",         createPrimitive(pLess0));
  2802.   addPair(rootContext, "0>",         createPrimitive(pGreater0));
  2803.   addPair(rootContext, "=",         createPrimitive(pEqual));
  2804.   addPair(rootContext, "<>",        createPrimitive(pNotEqual));
  2805.   addPair(rootContext, "<",         createPrimitive(pLess));
  2806.   addPair(rootContext, "<=",         createPrimitive(pLessEq));
  2807.   addPair(rootContext, ">",         createPrimitive(pGreater));
  2808.   addPair(rootContext, ">=",         createPrimitive(pGreaterEq));
  2809.   addPair(rootContext, "u<",         createPrimitive(pULess));
  2810.   addPair(rootContext, "u>",         createPrimitive(pUGreater));
  2811.   addPair(rootContext, "min",         createPrimitive(pMin));
  2812.   addPair(rootContext, "max",         createPrimitive(pMax));
  2813.   addPair(rootContext, "between",     createPrimitive(pBetween));
  2814.  
  2815.  
  2816.   /* Logical primitives */
  2817.   addPair(rootContext, "and",         createPrimitive(pAnd));
  2818.   addPair(rootContext, "or",         createPrimitive(pOr));
  2819.   addPair(rootContext, "xor",         createPrimitive(pXor));
  2820.   addPair(rootContext, "not",         createPrimitive(pNot));
  2821.   addPair(rootContext, "<<",        createPrimitive(pShiftLeft));
  2822.   addPair(rootContext, ">>",        createPrimitive(pShiftRight));
  2823.  
  2824.  
  2825.   /* Control structure primitives */
  2826.   addPair(rootContext, "(branch)",    createPrimitive(pBranch)); hide();
  2827.   addPair(rootContext, "(if)",         createPrimitive(poIf)); hide();
  2828.   addPair(rootContext, "(do)",         createPrimitive(poDo)); hide();
  2829.   addPair(rootContext, "(-do)",     createPrimitive(poStraightDo)); hide();
  2830.   addPair(rootContext, "(loop)",     createPrimitive(poLoop)); hide();
  2831.   addPair(rootContext, "(+loop)",     createPrimitive(poAddLoop)); hide();
  2832.   addPair(rootContext, "unloop",    createPrimitive(pUnloop));
  2833.   addPair(rootContext, "leave",     createPrimitive(pLeave)); 
  2834.  
  2835.  
  2836.   /* System primitives */
  2837.   addPair(rootContext, "reboot",     createPrimitive(pReboot)); hide();
  2838.   addPair(rootContext, "noop",        createPrimitive(pNoop));
  2839.  
  2840.  
  2841.   /* Debugging, decompilation, and tracing primitives */
  2842.   addPair(rootContext, "debugExit", createPrimitive(debugExit)); hide();
  2843.   addPair(rootContext, "resume",     createPrimitive(resume)); 
  2844.   addPair(rootContext, "trace",        createPrimitive(traceInterpreter));
  2845.   addPair(rootContext, "fullTrace",    createPrimitive(fullTraceInterpreter));
  2846.   addPair(rootContext, "endTrace",    createPrimitive(ownLongJmp));
  2847.   addPair(rootContext, "see",        createPrimitive(pSee));
  2848. /*  addPair(rootContext, "image",        createPrimitive(pImage)); */
  2849.  
  2850.  
  2851.   /* Multitasker primitives */
  2852.   addPair(rootContext, "up",        createPrimitive(pUp));
  2853.   addPair(rootContext, "multitasking",createPrimitive(pMultitasking));
  2854.   addPair(rootContext, "running",    createPrimitive(pRunning));
  2855.   addPair(rootContext, "#tasks",    createPrimitive(pCountTasks));
  2856.   addPair(rootContext, "#running",    createPrimitive(pCountRunningTasks));
  2857.   addPair(rootContext, "basePriority",createPrimitive(pBasePriority));
  2858.   addPair(rootContext, "taskingMode",createPrimitive(pMtaskMode));
  2859.   addPair(rootContext, "preemptive", createPrimitive(pPreemptive));
  2860.   addPair(rootContext, "cooperative",createPrimitive(pCooperative));
  2861.   addPair(rootContext, "yield",     createPrimitive(yield));
  2862.   addPair(rootContext, "<|",         createPrimitive(pIOff));
  2863.   addPair(rootContext, "|>",         createPrimitive(pIOn));
  2864.   addPair(rootContext, "activate",     createPrimitive(pActivate));
  2865.   addPair(rootContext, "suspend",     createPrimitive(pSuspend));
  2866.   addPair(rootContext, "does",        createPrimitive(pTaskDoes));
  2867.   addPair(rootContext, "raisePriority",    createPrimitive(pRaisePriority));
  2868.   addPair(rootContext, "lowerPriority",    createPrimitive(pLowerPriority));
  2869.   addPair(rootContext, "resetPriorities",createPrimitive(pResetPriorities));
  2870.   addPair(rootContext, ">taskData",        createPrimitive(pToTaskData));
  2871.   addPair(rootContext, ">taskReturn",    createPrimitive(pToTaskReturn));
  2872.   addPair(rootContext, ">taskContext",    createPrimitive(pToTaskCtxt));
  2873.  
  2874.  
  2875.   /* File primitives */
  2876.   addPair(rootContext, "pushInfile",    createPrimitive(pPushInfile));
  2877.   addPair(rootContext, "popInfile",        createPrimitive(pPopInfile));
  2878.   addPair(rootContext, "resetInfiles",    createPrimitive(pResetInfiles));
  2879.   addPair(rootContext, "pushOutfile",    createPrimitive(pPushOutfile));
  2880.   addPair(rootContext, "popOutfile",    createPrimitive(pPopOutfile));
  2881.   addPair(rootContext, "resetOutfiles",    createPrimitive(pResetOutfiles));
  2882.   addPair(rootContext, "errorTo",        createPrimitive(pErrfilePush));
  2883.   addPair(rootContext, "consoleTo",        createPrimitive(pConfilePush));
  2884.  
  2885.  
  2886.   /* Block file primitives */
  2887.   /* (defined in a separate file) */
  2888.   addPair(rootContext, "open-blockfile",createPrimitive(pOpenBlockFile));
  2889.   addPair(rootContext, "close-blockfile",createPrimitive(pCloseBlockFile));
  2890.   addPair(rootContext, "block",            createPrimitive(pBlock));
  2891.   addPair(rootContext, "update",        createPrimitive(pUpdate));
  2892.   addPair(rootContext, "discard",        createPrimitive(pDiscard));
  2893.   addPair(rootContext, "save-buffers",    createPrimitive(pSaveBuffers));
  2894.   addPair(rootContext, "empty-buffers",    createPrimitive(pEmptyBuffers));
  2895.   addPair(rootContext, "more",            createPrimitive(pMore));
  2896.   addPair(rootContext, "capacity",        createPrimitive(pCapacity));
  2897.  
  2898.  
  2899.   /* Dictionary primitives */
  2900.   addPair(rootContext, "number",        createPrimitive(pNumber));
  2901.   addPair(rootContext, "search",         createPrimitive(pSearch));
  2902.   addPair(rootContext, "searchThis",     createPrimitive(pSearchThis));
  2903.   addPair(rootContext, "immediate?",    createPrimitive(pQImmed));
  2904.  
  2905.  
  2906.   /* Internal structure primitives */
  2907.   addPair(rootContext, "<buildContext>",createPrimitive(pBuildCtxt)); hide();
  2908.   addPair(rootContext, "<buildName>",     createPrimitive(pBuildPair)); hide();
  2909.   addPair(rootContext, "<buildObject>",    createPrimitive(pBuildObj)); hide();
  2910.   addPair(rootContext, "<buildStore>",    createPrimitive(pBuildStore)); hide();
  2911.   addPair(rootContext, "<buildString>",    createPrimitive(pBuildStr)); hide();
  2912.   addPair(rootContext, "<buildBGTask>",    createPrimitive(pBuildBGTask)); hide();
  2913.   addPair(rootContext, "<deleteTask>",    createPrimitive(pDeleteTask)); hide();
  2914.   addPair(rootContext, "<killTask>",    createPrimitive(pKillTask)); hide();
  2915.   addPair(rootContext, "<deleteName>",    createPrimitive(pDeleteName)); hide();
  2916.   addPair(rootContext, "<renameName>",    createPrimitive(pRenameName)); hide();
  2917.   addPair(rootContext, "<mkdir>",        createPrimitive(pBuildDir)); hide();
  2918.   addPair(rootContext, "<shallowCopy>",    createPrimitive(pShallowCopyObj)); hide();
  2919.   addPair(rootContext, "<derive>",        createPrimitive(pDeriveObject)); hide();
  2920.   addPair(rootContext, "<resize>",        createPrimitive(pResizeObj)); hide();
  2921.   addPair(rootContext, "<expand>",        createPrimitive(pExpandObj)); hide();
  2922.   addPair(rootContext, "<expandFamily>",createPrimitive(pExpandFamily)); hide();
  2923.   addPair(rootContext, "<optimize>",    createPrimitive(pOptimizeObj)); hide();
  2924.   addPair(rootContext, "<dispose>",        createPrimitive(pDisposeObject)); hide();
  2925.   addPair(rootContext, "<free>",        createPrimitive(pFree)); hide();
  2926.   addPair(rootContext, "<freeStore>",    createPrimitive(pFreeStore)); hide();
  2927.   addPair(rootContext, "<recompile>",    createPrimitive(pRecompile)); hide();
  2928.   addPair(rootContext, "<rebind>",        createPrimitive(pRebind)); hide();
  2929.   addPair(rootContext, "<reorganize>",    createPrimitive(pReorganize)); hide();
  2930.   addPair(rootContext, "<rePair>",        createPrimitive(pRePair)); hide();
  2931.  
  2932.  
  2933.   /* Internal structure offsets */
  2934.   addPair(rootContext, "name>object",    createPrimitive(pPairToObj)); hide();
  2935.   addPair(rootContext, "name'object",    createPrimitive(pPairOFA)); hide();
  2936.   addPair(rootContext, "name'name",        createPrimitive(pPairNFA)); hide();
  2937.   addPair(rootContext, "name'flags",    createPrimitive(pPairFFA)); hide();
  2938.   addPair(rootContext, "name'prev",        createPrimitive(pPairLFA)); hide();
  2939.   addPair(rootContext, "name'succ",        createPrimitive(pPairSFA)); hide();
  2940.   addPair(rootContext, "name'context",    createPrimitive(pPairCFA)); hide();
  2941.   addPair(rootContext, "object>name",    createPrimitive(pObjToPair)); hide();
  2942.   addPair(rootContext, "object>typename",createPrimitive(pObjToTypeName)); hide();
  2943.   addPair(rootContext, "object>store",    createPrimitive(pObjToStore)); hide();
  2944.   addPair(rootContext, "object'store",    createPrimitive(pObjectMFA)); hide();
  2945.   addPair(rootContext, "object'size",    createPrimitive(pObjectSFA)); hide();
  2946.   addPair(rootContext, "object>context",createPrimitive(pObjToContext)); hide();
  2947.   addPair(rootContext, "context'thread",createPrimitive(pContextThread)); hide();
  2948.   addPair(rootContext, "context'first", createPrimitive(pContextFirst)); hide();
  2949.   addPair(rootContext, "context'latest",createPrimitive(pContextLatest)); hide();
  2950.   addPair(rootContext, "context'family",createPrimitive(pContextFamily)); hide();
  2951.   addPair(rootContext, "context'parents",createPrimitive(pContextParents)); hide();
  2952.   addPair(rootContext, "context'children",createPrimitive(pContextChildren)); hide();
  2953.   addPair(rootContext, "checkSystemValidity",createPrimitive(pCheckSystem)); 
  2954.  
  2955.  
  2956.   /* Object-oriented primitives */
  2957.   addPair(rootContext, "self",        createPrimitive(pSelf));
  2958.   addPair(rootContext, "&",            createPrimitive(pPrevSelf));
  2959.   addPair(rootContext, ">self",        createPrimitive(pToSelf)); hide();
  2960.   addPair(rootContext, "self>",        createPrimitive(pSelfFrom)); hide();
  2961.   addPair(rootContext, "self>drop",    createPrimitive(pSelfDrop)); hide();
  2962.   addPair(rootContext, "resetCp",    createPrimitive(resetContext)); hide();
  2963.   addPair(rootContext, "cdepth",    createPrimitive(pCDepth));
  2964.   addPair(rootContext, ".cs",        createPrimitive(pPrintCStack));
  2965.   addPair(rootContext, "resizeContextStack",createPrimitive(pResizeContext));
  2966.   addPair(rootContext, ">send",        createPrimitive(pSend)); hide();
  2967.   addPair(rootContext, ">resend",    createPrimitive(pResend)); hide();
  2968.   addPair(rootContext, "respondsTo",createPrimitive(pRespondsTo));
  2969.   addPair(rootContext, "hasContext", createPrimitive(pHasContext));
  2970.   addPair(rootContext, ">area",     createPrimitive(pToArea));
  2971.   addPair(rootContext, "area0",     createPrimitive(pAreaZero));
  2972.   addPair(rootContext, "area#",     createPrimitive(pAreaSize));
  2973.  
  2974. }
  2975.  
  2976.  
  2977.